java-设计模式-原型模式(克隆模式)

  • 为什么使用原型模式

1、假如我有一个对象,如下:

public static void main(String[] args) {
    // 创建对象
    Condition condition1 = new Condition.Builder()
            .setStr1("aa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition1:"+condition1.toString());
}

输出:
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}

2、我还想要一个对象,但是除了属性 str1 的值不一样之外,其他的值都一样,怎么办?

public static void main(String[] args) {
    // 创建对象
    Condition condition1 = new Condition.Builder()
            .setStr1("aa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition1:"+condition1.toString());

    Condition condition2 = new Condition.Builder()
            .setStr1("aaaa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition2:"+condition2.toString());
}
输出:
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition2:Condition{str1='aaaa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}

3、也许你会说,为什么这样搞?这样搞不行吗,如下:

public static void main(String[] args) {
    // 创建对象
    Condition condition1 = new Condition.Builder()
            .setStr1("aa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition1:"+condition1.toString());

    Condition condition2 = condition1;
    condition2.setStr1("aaaa");
    System.out.println("condition2:"+condition2.toString());
}
输出:
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition2:Condition{str1='aaaa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}

 4、好吧,我们再往下看:

public static void main(String[] args) {
    // 创建对象
    Condition condition1 = new Condition.Builder()
            .setStr1("aa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition1:"+condition1.toString());

    Condition condition2 = condition1;
    condition2.setStr1("aaaa");
    System.out.println("condition2:"+condition2.toString());

    // 看这里
    System.out.println("condition1:"+condition1.toString());
}
输出:
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition2:Condition{str1='aaaa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition1:Condition{str1='aaaa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}

我们发现,condition2对象修改某个属性值之后,condition1对象的属性值也变了;因为condition1和condition2虽然是内存中两个地址,但是他们指向堆中同一个对象,所以他们都对这个对象敏感

5、那怎么办?

  1. 先让我们的类 Condition 实现 Cloneable 接口
  2. 再重写 clone() 方法
public class Condition implements Cloneable{

    ......

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public static void main(String[] args) {
    // 创建对象
    Condition condition1 = new Condition.Builder()
            .setStr1("aa")
            .setStr2("bb")
            .setStr3("cc")
            .setStr4("dd")
            .setStr5("ee")
            .setStr6("rr")
            .setStr7("tt")
            .setStr8("yy")
            .setStr9("uu")
            .setStr10("ii")
            .build();
    System.out.println("condition1:"+condition1.toString());

    try {
        Condition condition2 = (Condition)condition1.clone();
        condition2.setStr1("aaaa");
        System.out.println("condition2:"+condition2.toString());
        System.out.println("condition1:"+condition1.toString());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }

}
输出:
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition2:Condition{str1='aaaa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}
condition1:Condition{str1='aa', str2='bb', str3='cc', str4='dd', str5='ee', str6='rr', str7='tt', str8='yy', str9='uu', str10='ii'}

综上:我们通过 clone() 方法,克隆出一个新的对象,两个对象不相互影响

  • 原型模式存在的问题
  1. 它是一种浅克隆技术(深克隆与浅克隆不在这里谈论)
  2. 需要为每一个类配备一个克隆方法
  3. 其他

猜你喜欢

转载自blog.csdn.net/m0_37524661/article/details/87877609