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

来源:互联网 发布:猴赛雷微信软件 编辑:程序博客网 时间:2024/06/02 19:20

原型模式

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

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

缺点:由于原型模式需要给每一个类都配备一个克隆的方法,这就需要在设计类时通盘考虑。因为在已有类的基础上添加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());            }}

新的问题: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);    }}//可以看到修改的不是同一对象变量