【3W2H设计模式】- 原型模式

简介: 【3W2H设计模式】- 原型模式

【3W2H设计模式】- 原型模式

一、WHAT 什么是原型模式

原型模式是创建者模式的一种,用于创建重复对象,且能保证性能。它提供了一种创建对象的最佳方式。

原型模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。

二、WHY 为什么用原型模式

原型模式实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式主要解决在运行期建立和删除原型。

三、WHEN 什么时候用原型模式

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。

四、HOW 如何实现原型模式

4.1 类图

4.2、原型模式组成与作用

编号 组成(角色) 作用
1 抽象原型(Prototype) 规定拷贝接口。
2 具体原型(Concrete Prototype) 被拷贝的对象。
3 客户(Client) 客户类提出创建对象的请求。

4.3、创建者模式代码示例

  • 创建一个抽象原型
public interface Prototype{
    int id = 0;
    String name = null;
    Prototype clone();
}
  • 实现原型创建具体的原型
public class ConcretePrototypeA implements Prototype {
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    private int id;
    private String name;
    @Override
    public ConcretePrototypeA clone() {
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        concretePrototype.setId(this.id);
        concretePrototype.setName(this.name);
        return concretePrototype;
    }
}
/*
 * 继承Prototype并创建类ConcretePrototypeB
 */
public class ConcretePrototypeB implements Prototype {
    public int getIdb() {
        return idb;
    }
    public void setIdb(int idb) {
        this.idb = idb;
    }
    public String getNameb() {
        return nameb;
    }
    public void setNameb(String nameb) {
        this.nameb = nameb;
    }
    public String getValueb() {
        return valueb;
    }
    public void setValueb(String valueb) {
        this.valueb = valueb;
    }
    private int idb;
    private String nameb;
    private String valueb;
    @Override
    public ConcretePrototypeB clone() {
        ConcretePrototypeB concretePrototype = new ConcretePrototypeB();
        concretePrototype.setIdb(this.idb);
        concretePrototype.setNameb(this.nameb);
        concretePrototype.setValueb(this.valueb);
        return concretePrototype;
    }
  • 使用 Prototype 类实现clone 对象。
public class Client {
    public static void main(String[] args) {
        ConcretePrototypeA concreteProductA=new ConcretePrototypeA();
        concreteProductA.setId(100);
        concreteProductA.setName("Clone ConcreteProtoTypeA");
        System.out.println(concreteProductA.getName());
        ConcretePrototypeA prototypeA=concreteProductA.clone();
        prototypeA.setId(100);
        prototypeA.setName("Clone PrototypeA");
        System.out.println(prototypeA.getName());
    }
}

4.4、通过浅拷贝创建新对象

在浅克隆中,如果源对象的成员变量是值类型,将复制一份给克隆对象;如果源对象的成员变量是引用类型,则将引用对象的地址复制一份给目标对象,也就是说源对象和目标对象的成员变量指向相同的内存地址。简言之,浅克隆,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

  • 继承Cloneable创建一个类ShallowClone
import java.util.List;
public class ShallowClone implements Cloneable{
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getAddr() {
        return addr;
    }
    public void setAddr(List<String> addr) {
        this.addr = addr;
    }
    private List<String> addr;
    @Override
    public ShallowClone clone() {
        try {
            return (ShallowClone) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
  • Client实现一个浅拷贝
import java.util.ArrayList;
import java.util.List;
public class ShallowCloneClinet {
 public static void main(String[] args) {
     ShallowClone superClone=new ShallowClone();
     superClone.setId(100);
     superClone.setName("赤木");
     List<String> attrList=new ArrayList<>();
     attrList.add("东京");
     attrList.add("京都");
     superClone.setAddr(attrList);
     System.out.println("superClone Id="+superClone.getId());
     System.out.println("superClone Id="+superClone.getName());
     ShallowClone superClone2=superClone.clone();
     superClone2.setId(10000);
     superClone2.setName("赤木");
     System.out.println("superClone2 Id="+superClone2.getId());
     System.out.println("superClone2 Id="+superClone2.getName());
     }
 }
  • 浅拷贝执行结果

4.5、通过序列化深拷贝创建对象

  • 继承Serializable创建SerializableClone
import java.io.*;
public class SerializableClone implements Serializable {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public SerializableClone deepClone() throws Exception {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        // 把流放在 tyr资源块中,程序结束java会自动关闭流资源
        try (ObjectOutputStream outputStream = new ObjectOutputStream(buf)) {
            outputStream.writeObject(this);
        }
        try (ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()))) {
            return (SerializableClone) inputStream.readObject();
        }
    }
}
  • Client实现一个深拷贝
public class SerializableClient {
    public static void main(String[] args) {
        SerializableClone clone=new SerializableClone();
        clone.setId(100);
        clone.setName("樱木花道");
        System.out.println("clone->Id:"+clone.getId());
        System.out.println("clone->Name:"+clone.getName());
        try {
            SerializableClone clone2 = clone.deepClone();
            clone2.setId(1000);
            clone2.setName("流川枫天");
            System.out.println("clone2->Id:"+clone2.getId());
            System.out.println("clone2->Name:"+clone2.getName());
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}
  • 深拷贝执行结果

五、HOW TO CHANGE(原型模式在代码中如何使用)

  • OA流程管理中复制功能
  • 项目管理中复制创建一个新项目
  • MES系统中BOM复制功能,通过复制功能创建一个类似的BOM

目录
相关文章
|
5月前
|
设计模式 安全 Java
面向对象编程的精髓:Java设计模式 - 原型模式(Prototype)完全参考手册
【4月更文挑战第7天】原型模式是OOP中的创建型设计模式,用于通过复制现有实例创建新实例,尤其适用于创建成本高或依赖其他对象的情况。它包括Prototype接口、ConcretePrototype实现和Client客户端角色。优点是性能优化、避免子类化和动态增加产品族。实现包括定义原型接口、实现具体原型和客户端调用克隆方法。最佳实践涉及确保克隆正确性、选择深拷贝或浅拷贝及考虑线程安全。但需注意克隆方法管理、性能开销和循环引用等问题。在Java中,实现Cloneable接口和覆盖clone方法可实现原型模式。
62 4
|
5月前
|
设计模式 Java 关系型数据库
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
23种设计模式 —— 原型模式【克隆羊、浅拷贝、深拷贝】
|
5月前
|
设计模式 安全 Java
【设计模式】原型模式
【设计模式】原型模式
|
22天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
10天前
|
设计模式 Java
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
|
3月前
|
设计模式
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
iLogtail设计模式问题之iLogtail中的原型模式是什么
|
3月前
|
设计模式 JavaScript
js设计模式【详解】—— 原型模式
js设计模式【详解】—— 原型模式
42 6
|
4月前
|
设计模式 Java
Java设计模式之原型模式详解
Java设计模式之原型模式详解
|
4月前
|
设计模式
原型模式-大话设计模式
原型模式-大话设计模式
|
4月前
|
设计模式 Java Spring
设计模式——原型模式
设计模式——原型模式