设计模式笔记之四(原型模式)
原型模式
原型模式就是需要创建多个实例的时候,以一个为原型,其他实例复制/克隆这个原型来获得相似的实例。
我们的实验室最近研究这个模式还是因为市场的原因,市场上由于长久以来的习俗和政策,对女人的需求比较大,所有我们就的扩大女人的生产线,但是由于资金的原因,我们不能投入硬件成本只能改进我们的方法。
首先我们得分析女人的构成:
class NvRen { private String name; private String head; private String body; private String type; public NvRen(String name, String head, String body, String type) { this.name = name; this.head = head; this.body = body; this.type = type; } }
我们以前生产女人的时候我们把预设好的名字,头型,身型,类型在创建女人的时候传入(好吧,我承认女人很难懂,但我们春秋笔法下~~)。
public class Prototype { public static void main(String[] args) { NvRen nvren1 = new NvRen("小责圆","瓜子脸","葫芦型","气质高雅型"); NvRen nvren2 = new NvRen("松岛丰","圆脸","葫芦型","邻家御姐型"); NvRen nvren3 = new NvRen("饭到爱","瓜子脸","葫芦型","可爱型"); NvRen nvren4 = new NvRen("罗玉风","面瓜脸","水桶型","恶心型"); } }
研究了很久,我们的市场部经理终于有了想法:由于高富帅客户不需要我们的产品,现在需求我们产品的客户基本上都属于丑矮穷搓撸的类型,他们对我们的产品也没有多少要求,只要有不同名字就行,我觉得我们可以批量生产女人,出厂的时候再给他们设置下不同的名字就行了,所以我们更改了我们的女人类:
class NvRen implements Cloneable { private String name; private String head; private String body; private String type; public NvRen(String name, String head, String body, String type) { this.name = name; this.head = head; this.body = body; this.type = type; } public void setName(String name) { this.name = name; } @Override protected NvRen clone() { NvRen nr = null; try { nr = (NvRen) super.clone(); } catch (CloneNotSupportedException e) { nr = new NvRen(this.name, this.head, this.body, this.type); } return nr; } }
现在我们就可以很Happy的批量生产了
public class Prototype { public static void main(String[] args) { NvRen nvren1 = new NvRen("小责圆", "瓜子脸", "葫芦型", "气质高雅型"); NvRen nvren2 = nvren1.clone(); nvren2.setName("松岛丰"); NvRen nvren3 = nvren1.clone(); nvren3.setName("饭到爱"); NvRen nvren4 = nvren1.clone(); // nvren4.setName("罗玉风"); //这个实在不好卖,即使只有名字和其他的不一样 nvren4.setName("苍老师"); } }
当我们的产品投放到市场的时候,却很是悲摧了,因为他们投诉我们生产的女人只有一个却顶着不同的名字到处卖。
我们只能再次研究,最后发现我们的一个工程师为了更加方便的生产,对我们的女人类作了些改变:
class RouTi { private String head; private String body; private String type; public RouTi(String head, String body, String type) { this.head = head; this.body = body; this.type = type; } } class NvRen implements Cloneable { private String name; private RouTi routi; public NvRen(String name, String head, String body, String type) { this.name = name; this.routi = new RouTi(head, body, type); } private NvRen(String name, RouTi routi) { this.name = name; this.routi = routi; } public void setName(String name) { this.name = name; } public RouTi getRouTi() { return this.routi; } @Override protected NvRen clone() { NvRen nr = null; try { nr = (NvRen) super.clone(); } catch (CloneNotSupportedException e) { nr = new NvRen(this.name, this.routi); } return nr; } }
我们做了一些测试发现这些女人虽然有不同的名字,但是她们共用一个肉体
public class Prototype { public static void main(String[] args) { NvRen nvren1 = new NvRen("小责圆", "瓜子脸", "葫芦型", "气质高雅型"); System.out.println(nvren1.getRouTi().toString()); NvRen nvren2 = nvren1.clone(); nvren2.setName("松岛丰"); System.out.println(nvren2.getRouTi().toString()); NvRen nvren3 = nvren1.clone(); nvren3.setName("饭到爱"); System.out.println(nvren3.getRouTi().toString()); NvRen nvren4 = nvren1.clone(); // nvren4.setName("罗玉风"); //这个实在不好卖,即使只有名字和其他的不一样 nvren4.setName("苍老师"); System.out.println(nvren4.getRouTi().toString()); } } //------> output //com.pattern.now.RouTi@1fc4bec //com.pattern.now.RouTi@1fc4bec //com.pattern.now.RouTi@1fc4bec //com.pattern.now.RouTi@1fc4bec
经研究发现:当我们使用clone方法的时候,我们做的只是浅克隆,浅克隆只会复制值类型的属性,引用类型的属性只会复制其引用(即指针)而不会复制整个引用的对象。
所以我们要克隆女人的时候还得克隆肉体:
class RouTi implements Cloneable { private String head; private String body; private String type; public RouTi(String head, String body, String type) { this.head = head; this.body = body; this.type = type; } @Override protected RouTi clone() { RouTi rt = null; try { rt = (RouTi) super.clone(); } catch (CloneNotSupportedException e) { rt = new RouTi(this.head, this.body, this.type); } return rt; } } class NvRen implements Cloneable { private String name; private RouTi routi; public NvRen(String name, String head, String body, String type) { this.name = name; this.routi = new RouTi(head, body, type); } private NvRen(String name, RouTi routi) { this.name = name; this.routi = routi; } public void setName(String name) { this.name = name; } public RouTi getRouTi() { return this.routi; } @Override protected NvRen clone() { NvRen nr = new NvRen(this.name, this.routi.clone()); return nr; } }
这时我们就能得到正确的结果:不同的女人有不同的肉体
//--->output //com.pattern.now.RouTi@1fc4bec //com.pattern.now.RouTi@dc8569 //com.pattern.now.RouTi@1bab50a //com.pattern.now.RouTi@c3c749
这是我们的一个宅男工程师提出一个问题: 当我们的的肉体类种新加一个属性叫likeWho,并且 值是女人类:
private NvRen likeWho;
哥只能说:遇到这种情况,要么是你的女人类设计得有问题,要么就只能放弃原型模式。