(五)原型模式(Prototype)

最后更新于:2022-04-01 15:48:14

原型模式就是通过一个原型对象来表明要创建的对象类型,然后用复制这个原型对象的方法来创建更多同类型的对象。 自己对原型模式简单理解的原理图如下: 具体属性没有添加: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-07-12_578455ccc8ed4.png) 原型模式里面关键点就在一个Cloneable接口和clone方法的重写 下面就通过一个配钥匙的例子简单的写了一个程序,起初一个一个抽象类,这样可以重写clone方法,如果是接口的话就得到子类里面把重写的方法具体声明,这样的话对于程序的复用性不是很好,于是就写了一个抽象的类KeyPrototype然后,写了两个子类继承一个客户端,代码如下: ~~~ package com.designpattern.prototype; public abstract class KeyPrototype implements Cloneable { private String color; private float length; private float thick; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return this.getClass() + " -> Color:" + this.getColor() + " Length:" + this.getLength() + " Thick:" + this.getThick(); } public String getColor() { return color; } public float getLength() { return length; } public float getThick() { return thick; } public void setColor(String color) { this.color = color; } public void setLength(float length) { this.length = length; } public void setThick(float thick) { this.thick = thick; } } ~~~ ~~~ package com.designpattern.prototype; public class CopperKey extends KeyPrototype { } ~~~ ~~~ package com.designpattern.prototype; public class AluminiumKey extends KeyPrototype { } ~~~ ~~~ package com.designpattern.prototype; public class Client { public static void main(String[] args) { KeyPrototype copperkey = new CopperKey(); copperkey.setColor("red"); copperkey.setLength(12); copperkey.setThick(2); System.out.println(copperkey); try { KeyPrototype aluminaumkey = (KeyPrototype) copperkey.clone(); aluminaumkey.setColor("yellow"); aluminaumkey.setLength(10); aluminaumkey.setThick(5); System.out.println(aluminaumkey); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } } ~~~ ~~~ class com.designpattern.prototype.CopperKey -> Color:red Length:12.0 Thick:2.0 class com.designpattern.prototype.CopperKey -> Color:yellow Length:10.0 Thick:5.0 ~~~ 这样就简单对前者进行的复制,很显然他们并不是一个对象,里面关于clone的东西做了一个简单的总结 同时来证明他们确实是两个对象,就是改动里面的属性不互相影响: 首先我创建了一个Dog类 ~~~ package com.note.clone; public class Dog/* implements Cloneable */{ private String color; private String name; public Dog(String name,String color){ this.name = name; this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getName() { return name; } public void setName(String name) { this.name = name; } /* @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); }*/ @Override public String toString() { return this.getClass()+" "+this.getName()+" "+this.getColor(); } } ~~~ 然后写了一个Tom类,其中Tom类里面有私有属性Dog ~~~ package com.note.clone; public class Tom implements Cloneable { private String color; private Dog dog = new Dog("mimi", "yellow");; private String name; @Override protected Object clone() throws CloneNotSupportedException { Tom o = null; o = (Tom)super.clone(); // o.setDog((Dog)o.getDog().clone()); return o; } public String getColor() { return color; } public Dog getDog() { return dog; } public String getName() { return name; } public void setColor(String color) { this.color = color; } public void setDog(Dog dog) { this.dog = dog; } public void setName(String name) { this.name = name; } @Override public String toString() { return this.getClass() + " " + this.getName() + " " + this.getColor() + "\n" + "Dog:" + this.dog; } } ~~~ 然后写了一个People类简单的对上述的两个程序进行测试: ~~~ package com.note.clone; public class People { public static void main(String[] args) { Tom tom = new Tom(); tom.setName("Tom"); tom.setColor("blue"); System.out.println(tom); System.out.println(); try { Tom tylo = (Tom) tom.clone(); tylo.setName("tylo"); tylo.setColor("red"); tylo.getDog().setName("lucky"); tylo.getDog().setColor("green"); System.out.println(tylo); System.out.println(); System.out.println(tom); System.out.println(); Dog dog = tylo.getDog(); dog.setName("hello"); dog.setColor("white"); System.out.println(tylo); System.out.println(); System.out.println(tom); System.out.println(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } } ~~~ 运行结果如下: ~~~ class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog mimi yellow class com.note.clone.Tom tylo red Dog:class com.note.clone.Dog lucky green class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog lucky green class com.note.clone.Tom tylo red Dog:class com.note.clone.Dog hello white class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog hello white ~~~ 这样很明确的表明了对于这两个对象的属性,自己的属性除了Dog以外都是自己的,没有对着对方的属性的改变而改变,但是Dog属性,两个对象的属性是一样的 那么这里就到了深度克隆 我们把Dog和Tom里注释掉的内容打开再运行People程序,运行结果如下: ~~~ class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog mimi yellow class com.note.clone.Tom tylo red Dog:class com.note.clone.Dog lucky green class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog mimi yellow class com.note.clone.Tom tylo red Dog:class com.note.clone.Dog hello white class com.note.clone.Tom Tom blue Dog:class com.note.clone.Dog mimi yellow ~~~ 很明显发现,两个对象的Dog属性也没有互相影响,说明了他们不是用的一个引用,这样也证明了上面的例子,他们分别是一个对象,达到了克隆复用的应用。 在原型模式中,可以动态的添加产品分类,而且对整体结构没有影响。 由于原型模式需要给每一个类都配备一个克隆方法,这就需要在这几类的时候通盘考虑,因为在已有类的基础上来添加clone操作时比较困难的,而且原型模式在实现深层的复制时,需要编写一定量的代码。
';