您的位置:首页 > 其它

设计模式的应用场景(4)--原型模式

2017-08-28 17:35 393 查看

原型模式

定义:通过一个原型对象来表明要创建的类型,然后复制这个原型对象的方法来创建更多同类型的对象。

优点:可以动态地添加产品类而且对整体结构没有影响。

缺点:由于原型模式需要给每一个类都配备一个克隆的方法,这就需要在设计类时通盘考虑。因为在已有类的基础上添加clone操作比较困难。

使用时机:比如有一个对象,在某一个时刻该对象中已经包含了一些有效值,此时可能会需要一个和该对象完全相同的新对象,并且此后对新对象的任何改动都不会影响到原来对象中的值。

下面以配钥匙为例:

//钥匙的原型类
public abstract class KeyPrototype implements Cloneable {
//钥匙长度
private float length;
//钥匙厚度
private float thick;
//钥匙颜色
private String color;
//复制对象
public Object clone() {
Object obj = null;
try {
obj = super.clone();
}catch (CloneNotSupportedException ex) {
System.out.println(ex);
}
return obj;
}
//获得长度
public float getLength(){
return length;
}
//设定长度
public void setLength(float length){
this.length = length;
}
//获得厚度
public float getThick(){
return thick;
}
//设定厚度
public void setThick(float thick){
this.thick = thick;
}
//获得颜色
public String getColor(){
return color;
}
//设定颜色
public void setColor(String color){
this.color = color;
}
}
//铜钥匙类
public class CopperKey extends KeyPrototype {
public CopperKey() {
setColor("黄色");
}
}
//铝钥匙类
public class AluminiumKey extends KeyPrototype {
public AluminiumKey() {
setColor("银色");
}
}
public class Client1 {
public static void main(String[] argv) {
KeyPrototype copperKey = new CopperKey();
copperKey.setLength(3.1f);
copperKey.setThick(0.5f);
//下面进行配钥匙:铜->铝
KeyPrototype aluminiumKey = (KeyPrototype)copperKey.clone();
aluminiumKey.setColor("银色");
System.out.println("铜钥匙的颜色:" + copperKey.getColor());
System.out.println("铝钥匙的颜色:" + aluminiumKey.getColor(
c5cb
));
}
}


新的问题:Java的clone方法实现的是浅复制,对基本类型的复制,这样的操作是没有问题的。但对非基本类型的变量,复制的是对象的引用,导致最后两个变量指向同一个对象。

解决方法:深复制

//浅复制
public class Dog  {
public  int legCounts;
public Dog(int legCounts) {
this.legCounts = legCounts;
}
public void changeLegCounts() {
this.legCounts *= 2;
}
public String toString() {
return Integer.toString(this.legCounts);
}
}
public class DogClone implements Cloneable{
public  int legCounts;
public Dog dog=new Dog(4);
public Object clone(){
Dog o = null;
try{
o = (Dog)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}

public class Client1 {
public static void main(String[] argv) {
DogClone dogClone = new DogClone();
dogClone.legCounts = 3;
System.out.println("原来的克隆狗腿数量:" + dogClone.legCounts);
System.out.println("原来的普条狗腿数量:" + dogClone.dog);
DogClone dogClone1 = (DogClone)dogClone.clone();
dogClone1.legCounts = 2;
Dog dog = dogClone1.dog;
dog.changeLegCounts();
System.out.println("克隆后原来的克隆狗腿数量:" + dogClone.legCounts);
System.out.println("克隆后原来的普条狗腿数量:" + dogClone.dog);
System.out.println("克隆后的克隆狗腿数量:" + dogClone1.legCounts);
System.out.println("克隆后的普条狗腿数量:" + dogClone1.dog);
}
}
//可以看到修改的是同一对象变量


//深复制
public class Dog  {
public  int legCounts;
public Dog(int legCounts) {
this.legCounts = legCounts;
}
public void changeLegCounts() {
this.legCounts *= 2;
}
public String toString() {
return Integer.toString(this.legCounts);
}
}

public class DogClone implements Cloneable{
public int legCounts;
public Dog dog = new Dog(4);
public Object clone(){
DogClone o = null;
try{
o = (DogClone)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
o.dog = (Dog)dog.clone();
return o;
}
}

public class Client1 {
public static void main(String[] argv) {
DogClone dogClone = new DogClone();
dogClone.legCounts = 3;
System.out.println("原来的克隆狗腿数量:" + dogClone.legCounts);
System.out.println("原来的普条狗腿数量:" + dogClone.dog);
DogClone dogClone1 = (DogClone)dogClone.clone();
dogClone1.legCounts = 2;
Dog dog = dogClone1.dog;
dog.changeLegCounts();
System.out.println("克隆后原来的克隆狗腿数量:" + dogClone.legCounts);
System.out.println("克隆后原来的普条狗腿数量:" + dogClone.dog);
System.out.println("克隆后的克隆狗腿数量:" + dogClone1.legCounts);
System.out.println("克隆后的普条狗腿数量:" + dogClone1.dog);
}
}
//可以看到修改的不是同一对象变量
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: