一、背景

原型模式具体怎么使用,下面我会详细讲,如果有那个地方讲的不到位了,请大家多多指教,共同学习,我尽量以白话的形式进行展示,废话不多说了,下面开始。

二、简单的原型设计模式

1.先来理解一个简单的原型模式的设计吧(原型对象Prototype.java)

public class Prototype implements Cloneable {
    protected Object clone()throws CloneNotSupportedException{
        return super.clone();
    }
}
public class ConcretePrototype extends Prototype {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2.测试类

public class CloneTest {
    public static void main(String[] args) {
        ConcretePrototype cp = new ConcretePrototype();
        cp.setAge(18);
        try {
            ConcretePrototype copy = (ConcretePrototype) cp.clone();
            System.out.println(copy.getAge());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

运行上面的代码,结果是:18

总结:一般我们来讲,要想创建两个不同的对象,需要的是调用一个类的构造方法的,是clone(克隆)复制的是字节码文件,创建出来的对象,不经过类的构造方法。这个就是我们的原型设计模式,但是这样写代码的话,可扩展性就不是那么好了,这个怎么讲呢,就是说,我们的类中如果有上百个属性,再这么写确实就不太好了,其实这正是原型模式什么时候用的时机,下面就讲讲具体的程序可扩展性。

三、概念以及支持的范围

1.对于能够直接拷贝其实际内容的数据类型/只支持9种,八大基本类型+String类型,这就是浅克隆。如果一个类中有不属于这几种类型的,或者更加复杂的类型,这时候我们可能就要用到了深克隆了。

2.浅克隆:仅仅克隆基本类型变量,而不克隆引用类型的变量。

   深克隆:既克隆基本类型变量,也克隆引用类型变量。

四、可扩展性的原型模式(不是最佳的)

1.这个也不符合,我只是贴出来和下面的作对比,不然你们看着就很懵逼了。

public class Monkey {
    //身高
    protected int height;
    //体重
    protected int weight;
    //生日
    protected Date birthday; //不是基本类型

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
public class GoldRingedStaff implements Serializable {
    private float height = 100;//长度
    private float diameter = 10;//直径
    //金箍棒长大
    public void grow(){
        this.diameter *= 2;
        this.height *=2;
    }
    //金箍棒缩小
    public void shrink(){
        this.diameter /=2;
        this.height /=2;
    }
}
//齐天大圣
public class TheGreatestSage extends Monkey implements Cloneable,Serializable {
    //金箍棒
    private GoldRingedStaff staff;
    //出生就有金箍棒了
    public TheGreatestSage(){
        this.staff = new GoldRingedStaff();
        this.birthday = new Date();
        this.height = 150;
        this.weight = 30;
    }
    public GoldRingedStaff getStaff() {
        return staff;
    }
    public void setStaff(GoldRingedStaff staff) {
        this.staff = staff;
    }

    //72变化 用clone,分身
    public Object clone(){
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
    //分身技能
    public void change(){
        TheGreatestSage copySage = (TheGreatestSage) clone();
        System.out.println("大圣本身的生日:"+this.getBirthday().getTime());
        System.out.println("克隆大圣的生日:"+copySage.getBirthday().getTime());
        System.out.println("大圣和克隆大圣是否是同一个对象:"+(this == copySage));
        System.out.println("大圣和克隆大圣的金箍棒是否是同一个:"+(this.getStaff() == copySage.getStaff

()));
    }
}

3.

public class TestPrototype {
    public static void main(String[] args) {
        TheGreatestSage sage = new TheGreatestSage();
        sage.change();
    }
}

结果:

      大圣本身的生日:1555833518960
      克隆大圣的生日:1555833518960
      大圣和克隆大圣是否是同一个对象:false
      大圣和克隆大圣的金箍棒是否是同一个:true

生日相同,金箍棒也相同,不符合要求啊,怎么办呢,这时候我们得修改代码,clone()方法重写。

五、最后贴一个最符合规定的

public class Monkey {
    //身高
    protected int height;
    //体重
    protected int weight;
    //生日
    protected Date birthday; //不是基本类型

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
public class GoldRingedStaff implements Serializable {
    private float height = 100;//长度
    private float diameter = 10;//直径
    //金箍棒长大
    public void grow(){
        this.diameter *= 2;
        this.height *=2;
    }
    //金箍棒缩小
    public void shrink(){
        this.diameter /=2;
        this.height /=2;
    }
}

 

//齐天大圣
public class TheGreatestSage extends Monkey implements Cloneable,Serializable {
    //金箍棒
    private GoldRingedStaff staff;
    //出生就有金箍棒了
    public TheGreatestSage(){
        this.staff = new GoldRingedStaff();
        this.birthday = new Date();
        this.height = 150;
        this.weight = 30;
    }
    public GoldRingedStaff getStaff() {
        return staff;
    }
    public void setStaff(GoldRingedStaff staff) {
        this.staff = staff;
    }

    //72变化 用clone,分身
    public Object clone(){
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            //return super.clone();
            //修改代码
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            TheGreatestSage copy = (TheGreatestSage) ois.readObject();
            copy.birthday = new Date();
            return copy;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //分身技能
    public void change(){
        TheGreatestSage copySage = (TheGreatestSage) clone();
        System.out.println("大圣本身的生日:"+this.getBirthday().getTime());
        System.out.println("克隆大圣的生日:"+copySage.getBirthday().getTime());
        System.out.println("大圣和克隆大圣是否是同一个对象:"+(this == copySage));
        System.out.println("大圣和克隆大圣的金箍棒是否是同一个:"+(this.getStaff() == copySage.getStaff()));
    }
}
public class TestPrototype {
    public static void main(String[] args) {
        TheGreatestSage sage = new TheGreatestSage();
        sage.change();
    }
}

结果:

大圣本身的生日:1555835467763
克隆大圣的生日:1555835467863
大圣和克隆大圣是否是同一个对象:false
大圣和克隆大圣的金箍棒是否是同一个:false 

这个就很符合现实了,你们可以跟上面的对比,看到底改动那个地方了。

六、结束

上面就是我对这个原型模式得理解,还需要在现实代码中磨练,共勉,如有不足请多多指教。

Always keep the faith!!!