程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

设计模式-原型模式

发布于2021-03-13 13:29     阅读(1004)     评论(0)     点赞(18)     收藏(3)


特点

原型模式属于创建型。用于创建拷贝复杂对象,避免重复创建对象发生的资源损耗,在一定程度上提升了性能。原型模式主要被分为浅拷贝和深拷贝2种模式,它主要实现了接口Cloneable,重写Object类中的clone方法。

浅拷贝

浅拷贝只能对基本类型(long,double,float,int,short,byte,boolean,char)和String类型有效果,对复杂的类型只能不能有效果。

public class Car implements Cloneable{

    private String model;
    private int wheelRadius;
    private boolean autoSeat;



    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

测试

@Test
public void testCloneable() throws CloneNotSupportedException {
    Car car = new Car().setModel("运动版").setAutoSeat(true).setWheelRadius(19);

    Car cloneCar1 = (Car) car.clone();
    cloneCar1.setModel("标准版");

    Car cloneCar2 = (Car) car.clone();
    cloneCar2.setAutoSeat(false);

    Car cloneCar3 = (Car) car.clone();
    cloneCar3.setWheelRadius(18);

    Car cloneCar4 = (Car) car.clone();

    log.info("car: {}",car);
    log.info("cloneCar1: {}",cloneCar1);
    log.info("cloneCar2: {}",cloneCar2);
    log.info("cloneCar3: {}",cloneCar3);
    log.info("cloneCar4: {}",cloneCar4);
}
2021-03-11 14:26:14.077  INFO 104540 --- [           main] org.example.singleton.PrototypeTest      : car: Car(super=org.example.prototype.Car@3afee9e3, model=运动版, wheelRadius=19, autoSeat=true)
2021-03-11 14:26:14.079  INFO 104540 --- [           main] org.example.singleton.PrototypeTest      : cloneCar1: Car(super=org.example.prototype.Car@4abc50d4, model=标准版, wheelRadius=19, autoSeat=true)
2021-03-11 14:26:14.080  INFO 104540 --- [           main] org.example.singleton.PrototypeTest      : cloneCar2: Car(super=org.example.prototype.Car@3afee9f5, model=运动版, wheelRadius=19, autoSeat=false)
2021-03-11 14:26:14.080  INFO 104540 --- [           main] org.example.singleton.PrototypeTest      : cloneCar3: Car(super=org.example.prototype.Car@3afee9a8, model=运动版, wheelRadius=18, autoSeat=true)
2021-03-11 14:26:14.080  INFO 104540 --- [           main] org.example.singleton.PrototypeTest      : cloneCar4: Car(super=org.example.prototype.Car@3afee9e3, model=运动版, wheelRadius=19, autoSeat=true)

Car类设置了3种数据类型,分别对3种类型进行测试,从测试日志和代码可以看到,当从car对象克隆出的cloneCar4没有对其属性进行更改,则拷贝出的对象与原对象相同,当修改其中一个属性后,对象的引用地址发生变化。

当将上面的代码改造一下

添加一个Wheel

public class Wheel {
    private int wheelRadius;
}

改造后的Car

public class Car implements Cloneable{

    private String model;
    private int wheelRadius;
    private boolean autoSeat;
    private Wheel wheel;


    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

测试代码

@Test
public void testSimpleCloneable() throws CloneNotSupportedException {
    Car car = new Car().setModel("运动版").setAutoSeat(true).setWheelRadius(19).setWheel(new Wheel().setWheelRadius(19));

    Car cloneCar1 = (Car) car.clone();
    cloneCar1.getWheel().setWheelRadius(18);

    log.info("car: {}",car);
    log.info("cloneCar1: {}",cloneCar1);
}

测试日志

2021-03-11 14:44:58.714  INFO 104856 --- [           main] org.example.singleton.PrototypeTest      : car: Car(super=org.example.prototype.Car@98bfe79e, model=运动版, wheelRadius=19, autoSeat=true, wheel=Wheel(super=org.example.prototype.Wheel@4d, wheelRadius=18))
2021-03-11 14:44:58.717  INFO 104856 --- [           main] org.example.singleton.PrototypeTest      : cloneCar1: Car(super=org.example.prototype.Car@98bfe79e, model=运动版, wheelRadius=19, autoSeat=true, wheel=Wheel(super=org.example.prototype.Wheel@4d, wheelRadius=18))

可以发现,car对象初始化时,wheel属性中的wheelRadius=19,当克隆出cloneCar1对象后,并且设置wheel属性中的wheelRadius=18后,不仅cloneCar1对象没有变化,还影响了原有对象的属性值,由此可见,当对象中存在某个复杂类型的对象时,浅拷贝并不适合使用。

深拷贝

当对象中存在复杂类型的对象时,包括数组、集合和其他自定义的类,应该使用深拷贝。

改造Wheel类,让它也实现Cloneable接口

public class Wheel implements Cloneable{
    private int wheelRadius;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

改造Car类的clone方法

 	@Override
    public Object clone() throws CloneNotSupportedException {
        Car car = (Car) super.clone();
        Wheel wheel = (Wheel) this.wheel.clone();
        car.setWheel(wheel);
        return car;
    }

测试代码

@Test
public void testDeepCloneable() throws CloneNotSupportedException {
    Car car = new Car().setModel("运动版").setAutoSeat(true).setWheelRadius(19).setWheel(new Wheel().setWheelRadius(19));

    Car cloneCar1 = (Car) car.clone();
    cloneCar1.getWheel().setWheelRadius(18);

    log.info("car: {}",car);
    log.info("cloneCar1: {}",cloneCar1);
}

日志信息

2021-03-11 15:16:04.530  INFO 104668 --- [           main] org.example.singleton.PrototypeTest      : car: Car(super=org.example.prototype.Car@98bfe79f, model=运动版, wheelRadius=19, autoSeat=true, wheel=Wheel(super=org.example.prototype.Wheel@4e, wheelRadius=19))
2021-03-11 15:16:04.533  INFO 104668 --- [           main] org.example.singleton.PrototypeTest      : cloneCar1: Car(super=org.example.prototype.Car@98bfe79e, model=运动版, wheelRadius=19, autoSeat=true, wheel=Wheel(super=org.example.prototype.Wheel@4d, wheelRadius=18))

从日志信息中查看到,重写clone方法后,car对象中的自定义类型拷贝成功,并不影响原对象。

原文链接:https://blog.csdn.net/u010659671/article/details/114668183



所属网站分类: 技术文章 > 博客

作者:忽明忽灭

链接:http://www.javaheidong.com/blog/article/114223/d8bf72623683923d88a3/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

18 0
收藏该文
已收藏

评论内容:(最多支持255个字符)