原型模式必知必会

简介: 原型模式必知必会

类图


1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png


实例


public interface Prototype{
    Prototype clone();
}


public class ConcretePrototypeA implements Prototype {
    private int age;
    private String name;
    private List hobbies;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List getHobbies() {
        return hobbies;
    }
    public void setHobbies(List hobbies) {
        this.hobbies = hobbies;
    }
    @Override
    public ConcretePrototypeA clone() {
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        concretePrototype.setAge(this.age);
        concretePrototype.setName(this.name);
        concretePrototype.setHobbies(this.hobbies);
        return concretePrototype;
    }
}


public class ConcretePrototypeB implements Prototype {
    @Override
    public Prototype clone() {
        return null;
    }
}


public class Client {
    private Prototype prototype;
    public Client(Prototype prototype){
        this.prototype = prototype;
    }
    public Prototype startClone(Prototype concretePrototype){
        return (Prototype)concretePrototype.clone();
    }
}


public class PrototypeTest {
    public static void main(String[] args) {
        // 创建一个具体的需要克隆的对象
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        // 填充属性,方便测试
        concretePrototype.setAge(18);
        concretePrototype.setName("prototype");
        List hobbies = new ArrayList<String>();
        concretePrototype.setHobbies(hobbies);
        System.out.println(concretePrototype);
        // 创建Client对象,准备开始克隆
        Client client = new Client(concretePrototype);
        ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype);
        System.out.println(concretePrototypeClone);
        System.out.println("克隆对象中的引用类型地址值:" + concretePrototypeClone.getHobbies());
        System.out.println("原对象中的引用类型地址值:" + concretePrototype.getHobbies());
        System.out.println("对象地址比较:"+(concretePrototypeClone.getHobbies() == concretePrototype.getHobbies()));
    }
}

1dc618a0ed9580ce8bfa6facb208c08f.png


深克隆


例子:

5d4c6812c8535adbb050f4ddf2e1bce8.png


public class Monkey {
    public int height;
    public int weight;
    public Date birthday;
}


public class JinGuBang implements Serializable {
    public float h = 100;
    public float d = 10;
    public void big(){
        this.d *= 2;
        this.h *= 2;
    }
    public void small(){
        this.d /= 2;
        this.h /= 2;
    }
}


public class QiTianDaSheng extends Monkey implements Cloneable,Serializable {
    public JinGuBang jinGuBang;
    public  QiTianDaSheng(){
        //只是初始化
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }
    //深克隆
    public Object deepClone(){
        try{
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            QiTianDaSheng copy = (QiTianDaSheng)ois.readObject();
            copy.birthday = new Date();
            return copy;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
    public QiTianDaSheng shallowClone(QiTianDaSheng target){
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        qiTianDaSheng.height = target.height;
        qiTianDaSheng.weight = target.height;
        qiTianDaSheng.jinGuBang = target.jinGuBang;
        qiTianDaSheng.birthday = new Date();
        return  qiTianDaSheng;
    }
    //浅克隆
    public QiTianDaSheng deep2(QiTianDaSheng target){
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        qiTianDaSheng.height = target.height;
        qiTianDaSheng.weight = target.height;
        qiTianDaSheng.jinGuBang =  target.jinGuBang;
        qiTianDaSheng.birthday = new Date();
        return  qiTianDaSheng;
    }
}


public class DeepCloneTest {
    public static void main(String[] args) {
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        try {
            QiTianDaSheng clone = (QiTianDaSheng)qiTianDaSheng.clone();
            System.out.println("深克隆:" + (qiTianDaSheng.jinGuBang == clone.jinGuBang));
        } catch (Exception e) {
            e.printStackTrace();
        }
        QiTianDaSheng q = new QiTianDaSheng();
        QiTianDaSheng n = q.shallowClone(q);
        System.out.println("浅克隆:" + (q.jinGuBang == n.jinGuBang));
    }
}


1dc618a0ed9580ce8bfa6facb208c08f.png


深克隆破坏单例解决方式


要么你我们的单例类不实现Cloneable接口;

要么我们重写clone()方法,在clone方法中返回单例对象即可,具体代码如下:


@Override
protected Object clone() throws CloneNotSupportedException{
  return INSTANCE;
}


Cloneable源码分析先看我们常用的ArrayList就实现了Cloneable接口,来看代码clone()方法的实现:`


public Object clone(){
  try{
  ArrayList<?>v=(ArrayList<?>)
  super.clone();v.elementData=Arrays.copyOf(elementData,size);
      v.modCount=0;
      return v;
  }catch(CloneNotSupportedExceptione){
  。。。
  }


个人理解


感觉和之前new出来一个对象,再set值一样,只是,这个set的功能在对象内部。对外只暴露一个clone或者其他自定义接口。


原型克隆和new的区别


5d4c6812c8535adbb050f4ddf2e1bce8.png


原型模式和抽象工厂模式的区别


46a9d80a6e05e4e3b19d57a0ee70bcdf.png


本质


本质: 克隆生成对象。


代码地址:


https://github.com/hufanglei/pattern-learn/tree/master/src/main/java/com/example/prototype


笔记地址 https://blog.csdn.net/baidu_21349635/article/details/106086578


相关文章
|
2月前
|
设计模式 缓存 自然语言处理
原型模式详解
原型模式是一种创建型设计模式,通过复制已有对象来创建新对象,而非直接实例化类。这种方式特别适用于对象创建成本高或需要深复制的场景。原型模式的优点包括性能优化、简化对象创建和动态增加产品种类,但也有深浅复制问题和对克隆方法的依赖等缺点。适用于对象创建成本高、状态动态变化和避免工厂模式复杂性的场景。核心角色包括抽象原型、具体原型和客户端。
60 1
|
8月前
|
Java 数据库
原型模式
原型模式
53 1
|
设计模式
2023-6-14-第五式原型模式
2023-6-14-第五式原型模式
79 0
|
9月前
|
缓存 数据库 C++
创建型 原型模式
创建型 原型模式
63 1
|
设计模式 Java 关系型数据库
原型模式解读
原型模式解读
|
安全 Java
创建型模式-原型模式
创建型模式-原型模式
135 0
|
设计模式 JSON JavaScript
我学会了,原型模式
原型模式属于创建型模式,这个类型的设计模式是将 对象的创建和使用解耦了,花式的去创建对象。
162 0
我学会了,原型模式
|
JSON Java uml
原型模式 与 建造者模式(1)
原型模式 与 建造者模式(1)
226 0
原型模式 与 建造者模式(1)
|
算法 uml
原型模式 与 建造者模式(4)
原型模式 与 建造者模式(4)
165 0
原型模式 与 建造者模式(4)
|
Java 测试技术 API
原型模式 与 建造者模式(2)
原型模式 与 建造者模式(2)
141 0
原型模式 与 建造者模式(2)