美文网首页
原型模式

原型模式

作者: 我可能是个假开发 | 来源:发表于2023-11-20 10:38 被阅读0次

一、定义

复制运行时的对象,克隆出一个一模一样的对象;
hashcode和引用地址不同,只有内容相同。

UML.png

原型模式:

  • 浅克隆:创建一个新对象,新对象的地址指向原来的引用
  • 深克隆:重新创建一个对象,不再指向原有的对象地址

基于二进制流,比new快

二、实现

实现Cloneable接口
对象克隆:

public class PrototypeImpl implements Cloneable {

    private ArrayList list = new ArrayList();

    @Override
    public PrototypeImpl clone() {

        PrototypeImpl prototype = null;
        try {
            // 对象克隆
            prototype = (PrototypeImpl)super.clone();
            // 克隆集合
            // 数组,容器,集合,对象引用需要另行克隆
            prototype.list =  (ArrayList)this.list.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return prototype;
    }
}
public class CreatePrototype extends PrototypeImpl {
    public void show(){
        System.out.println("原型模式的实现类......");
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        CreatePrototype prototype = new CreatePrototype();
        // 克隆出一个新的对象
        CreatePrototype prototype1= (CreatePrototype)prototype.clone();
        prototype1.show();
    }
}

三、深度克隆

public class Person implements Cloneable{

    private String name;

    private Child child;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Child getChild() {
        return child;
    }

    public void setChild(Child child) {
        this.child = child;
    }

    @Override
    protected Person clone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", child=" + child +
                '}';
    }

    public Person(String name) {
        this.name = name;
    }
}
public class Child implements Cloneable{

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Child(String name) {
        this.name = name;
    }

    @Override
    protected Child clone() {
        try {
            return (Child) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Child{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class Test {

    public static void main(String[] args) {
        Person person = new Person("父亲");
        person.setChild(new Child("孩子"));

        //Person{name='父亲', child=Child{name='孩子'}}
        System.out.println(person);

        Person clonePerson = person.clone();

        //Person{name='父亲', child=Child{name='孩子'}}
        System.out.println(clonePerson);

        //false
        System.out.println(person==clonePerson);
    }
}

浅克隆:
存在的问题:复制的是引用地址,会导致克隆对象的修改影响了原有对象。

public class Test {

    public static void main(String[] args) {
        Person person = new Person("父亲");
        person.setChild(new Child("孩子"));

        //person:Person{name='父亲', child=Child{name='孩子'}}
        System.out.println("person:"+person);

        Person clonePerson = person.clone();
        clonePerson.getChild().setName("孩子2");

        //clonePerson:Person{name='父亲', child=Child{name='孩子2'}}
        System.out.println("clonePerson:"+clonePerson);
        
        //person:Person{name='父亲', child=Child{name='孩子2'}}
        System.out.println("person:"+person);
        
    }
}

1.重写clone方法,依次调用成员变量的clone方法

    @Override
    protected Person clone() {
        try {
            Person person = (Person) super.clone();
            Child child = person.getChild().clone();
            person.setChild(child);
            return person;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
public class Test {

    public static void main(String[] args) {
        Person person = new Person("父亲");
        person.setChild(new Child("孩子"));

        //person:Person{name='父亲', child=Child{name='孩子'}}
        System.out.println("person:"+person);

        Person clonePerson = person.clone();
        clonePerson.getChild().setName("孩子2");

        //clonePerson:Person{name='父亲', child=Child{name='孩子2'}}
        System.out.println("clonePerson:"+clonePerson);

        //person:Person{name='父亲', child=Child{name='孩子'}}
        System.out.println("person:"+person);

    }
}

2.通过序列化和反序列化实现

类实现序列化

public class Person implements Cloneable,Serializable
public class Child implements Cloneable, Serializable
    @Override
    protected Person clone() {
        ByteArrayOutputStream byteArrayOutputStream =null;
        ObjectOutputStream objectOutputStream =null;
        ByteArrayInputStream byteArrayInputStream =null;
        ObjectInputStream objectInputStream =null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);

            byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Person person = (Person)objectInputStream.readObject();
            return person;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                byteArrayOutputStream.close();
                byteArrayInputStream.close();
                objectOutputStream.close();
                objectInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

3.使用工具类来实现序列化和反序列化

  • BeanUtils
  • MapStruct

相关文章

  • 第3章 创建型模式-原型模式

    一、原型模式简介 二、原型模式的优点 ■ 三、原型模式的使用场景 ■ 四、原型模式的实例

  • 设计模式之原型模式(Prototype 模式)

    引入原型模式 原型模式的实例 为什么需要使用原型模式 引入原型模式 如果读者很熟悉javascript的话,对原型...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 设计模式之原型模式(创建型)

    [TOC] 模式定义 原型模式(Prototype Pattern):原型模式是提供一个原型接口,提供原型的克隆,...

  • 原型模式C++

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式结构图 原型模式基本代码 原型...

  • 设计模式:原型

    原型模式基本介绍原型模式的实现源码中的原型模式记录 原型模式基本介绍 定义:用原型实例指定创建对象的种类,并通过复...

  • js集成

    原始继承模式--原型链 2:借用构造函数 3:共享构造原型 4:圣杯模式原型链; 构造函数; 共享原型; 圣杯模式...

  • 关于JavaScript创建对象的多种方式

    JavaScript创建对象的方法 工厂模式 构造函数模式 原型模式 组合使用构造函数模式和原型模式 动态原型模式...

  • 前端面试题总结【37】:javascript对象的几种创建方式

    工厂模式 构造函数模式 原型模式 混合构造函数和原型模式 动态原型模式 寄生构造函数模式 稳妥构造函数模式 推荐:...

  • 设计模式之原型模式

    原型模式 原型模式(prototype)是指原型实例指向对象的种类,并且通过拷贝这些原型创建新的对象 模式作用: ...

网友评论

      本文标题:原型模式

      本文链接:https://www.haomeiwen.com/subject/mljmwdtx.html