小言_互联网的博客

设计模式——原型设计模式

311人阅读  评论(0)

原型设计模式

定义

指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

特点

不需要知道任何创建的细节,不调用构造函数

类型:创建型

使用场景

类初始化消耗较多资源
new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
构造函数比较复杂
循环体中生产大量对象时

原型模式优缺点

优点:
原型模式性能比直接new一个对象性能高
简化创建过程
缺点:
必须配备克隆方法
对克隆复杂对象或对克隆出的对象进行复杂改造时,容易引入风险
深拷贝、浅拷贝要运用得当

原型——扩展:深克隆 浅克隆

实例

原型模式通过clone的方式来创建另一个对象,而不是直接调用构造方法。这里就涉及到深克隆与浅克隆的坑。

实例:Pig类需要实现Cloneable接口

public class Pig implements Cloneable {
    private String name;
    private Date birthday;

    public Pig(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

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

    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", birthday=" + birthday +
                '}'+super.toString();
    }
}

调用

public class Test {
    public static void main(String[] args) {
        try {
            Date birthday = new Date(0L);
            Pig pig = new Pig("佩奇", birthday);
            Pig pig1 = (Pig) pig.clone();
            System.out.println(pig.toString());
            System.out.println(pig1.toString());

            pig.getBirthday().setTime(1200L);
            System.out.println(pig.toString());
            System.out.println(pig1.toString());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

    }
}

此时的打印信息:

Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28

此时可以发现在只修改pig的birthday的时间的时候,pig1的时间也发生了变化。这样就出现了问题,也就是我们说的bug,不难发现要修改这个bug,需要对pig类的clone方法进行修改,如下:

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Pig pig= (Pig) super.clone();
        pig.birthday= (Date) pig.birthday.clone();
        return pig;
    }

即对pig中引用对象birthday也进行拷贝

修改代码之后打印如下:

Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28

小结

原型模式使用的时候需要小心深拷贝与浅拷贝带来的bug


转载:https://blog.csdn.net/danfengw/article/details/95110266
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场