天天看點

設計模式——原型設計模式

原型設計模式

定義

指原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。

特點

不需要知道任何建立的細節,不調用構造函數

類型:建立型

使用場景

類初始化消耗較多資源

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      

小結