关于java:Prototype原型模式

43次阅读

共计 1839 个字符,预计需要花费 5 分钟才能阅读完成。

参考:https://www.cnblogs.com/betterboyz/p/9356190.html

简介:

原型模式要求对象实现一个“克隆”本身的接口,这样就能够通过复制一个实例对象自身来创立一个新的实例。这样一来,通过原型实例创立新的对象,就不再须要关怀这个实例自身的类型,只有实现了克隆本身的办法,就能够通过这个办法来获取新的对象,而无须再去通过 new 来创立

模式类图:


Object: java 中的 Object 类,提供了 clone() 办法
ConcreteObject1,ConcreteObject1: 实现了克隆办法的具体类

应用场景:

实际上这个克隆跟 new 可能差不多,只不过 new 进去的对象,外面的属性都是默认值,如果须要产生大批量对象,并且这些对象的属性值大部分或者全都雷同的状况下,应用克隆,会比拟省事儿

模式实例:

public class Test {public static void main(String[] args) throws Exception {Person p1 = new Person();
        Person p2 = (Person)p1.clone();
        System.out.println("p1.loc == p2.loc?" + (p1.loc == p2.loc));
        p1.loc.street.reverse();
        System.out.println(p2.loc.street);
        p1.name = new String("alice");
        System.out.println("p1.name:"+p1.name);
        System.out.println("p2.name:"+p2.name);
    }
}
class Person implements Cloneable {
    int age = 8;
    int score = 100;
    String name = new String("jack");
    Location loc = new Location(new StringBuilder("bj"), 22);
    @Override
 public Object clone() throws CloneNotSupportedException {Person p = (Person)super.clone();
        p.loc = (Location)loc.clone();
        return p;
    }
}
class Location implements Cloneable {
    StringBuilder street;
    int roomNo;
    @Override
 public String toString() {
        return "Location{" +
                "street='" + street + '''+", roomNo="+ roomNo +'}';
    }
    public Location(StringBuilder street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
    }
    @Override
 public Object clone() throws CloneNotSupportedException {return super.clone();
    }
}

测试后果:

总结:此处有一个须要留神的中央,那就是如上代码中,Person 类当中用一个援用是 Location, 那么在 Person 实现了 clone 办法之后,Location 也须要实现 clone 办法,否则的话克隆进去的对象跟原对象的 Location 指向同一个援用,扭转其中的一个对象的 Location, 另一个也会跟着改,就比拟不合理;除此之外 String 属性也是属于援用类型,那么它会不会有这个问题呢,分两种状况来看,

第一:String name = “jack”;
这种状况不存在,因为 String 自身是不可变的,并且它指向了常量池外面的一个常量,如果扭转 String,只是将 String 的援用指向常量池外面的另一个常量,原来的那个常量并没有被扭转,原来的对象也不会被扭转

第二种 String name = new String(“jack”);
这种状况也不存在问题,如果 p1.name = new String(“jack”), 将 p1 克隆出 p2,改 p2.name = “alice”; 或者 p2.name = new String(“alice”),第一种改法,将 p2.name 的援用间接指向了常量池,不会影响 p1, 第二种改法相当于 new 了一个新的 String 对象付给 p2.name,也不会影响 p1,所以 String 虽是援用类型,然而不会存在这个问题

正文完
 0