【原型模式】详解

一.概念

原型模式是一种创建型设计模式,它的主要思想是通过复制现有对象来创建新对象,而不是通过实例化一个类来创建。在原型模式中,我们称被复制的对象为原型(Prototype),新创建的对象为克隆体(Clone)。

在Java中,使用原型模式可以通过实现Cloneable接口和重写Object类的clone()方法来实现。

以下是原型模式的工作原理:

  1. 首先,需要定义一个需要克隆的原型类,并实现Cloneable接口。
  2. 在Cloneable接口中定义了一个clone()方法,该方法返回一个与原型对象相同的新对象。
  3. 当需要创建新对象时,可以先通过调用原型对象的clone()方法来创建一个新对象,然后再根据需要修改新对象的属性。
    优缺点
    原型模式的优点包括:
  4. 提高对象创建效率:使用原型模式创建对象比使用new方法创建对象更加高效,因为克隆操作不需要进行类的初始化等操作。
  5. 简化对象的创建过程:原型模式可以简化创建对象的过程,避免了重复创建相似对象的过程。
  6. 支持动态配置:可以根据需要进行动态配置,即根据原型对象创建多个变体对象。
    原型模式的缺点包括:
  7. 克隆对象破坏单一职责原则:克隆对象需要对原型对象的属性进行拷贝,这可能会导致对象破坏单一职责原则。
  8. 克隆对象需要与原型类保持一致:克隆对象需要与原型对象保持一致,否则可能会导致不一致的状态。

二.原型模式详解

原型模式结构

原型模式包含以下3个角色:

Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类也可以是接口,甚至还可以是具体实现类。

ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。

Client(客户类):在客户类中,让一个原型对象克隆自身从而创建一个新的对象,只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。

深克隆与浅克隆

深拷贝与浅拷贝

原型模式使用

通用实现方法

抽象原型类代码:

复制代码
public abstract class Prototype {
    public abstract Prototype clone();
}

具体原型类代码

复制代码
public class ConcretePrototype extends Prototype {
    private String name; // 成员变量
    public void setName(String name) {
        this.name = name;
    }
    public void getName() {
        return this.name;
    }
    // 克隆方法实现
    public Prototype clone() {
        Prototype prototype = new ConcretePrototype(); // 创建新对象
        prototype.setName(this.name);
        return prototype;
    }
}

java语言中clone()和cloneable接口

所有java类均继承自java.long.Object类,Object类提供了一个clone方法,可以将一个java对象复制一份。因此在java中可以直接使用Object提供clone方法来实现对象的浅克隆

注意能实现克隆的java类都必须实现一个标识接口Cloneable,表示这里java类支持被复制。如果没有实现这个接口调用clone方法,java编译器将抛出CloneNotSupportedException异常:

复制代码
public class ConcretePrototype implements Cloneable {
    public Prototype clone() {
        Object object = null;
        try {
            object = super.clone(); // 浅克隆
        } catch (CloneNotSupportedException exception) {
            System.err.println("Not support Cloneable");
        }
        return (Prototype)object;
    }
}

为了获取对象的一个克隆,可以直接利用Object类的clone方法:

  1. 在派生类中覆盖基类的clone方法,声明为public
  2. 在派生了中的clone方法中调用super.clone
  3. 派生类需要实现Cloneable接口
    应用举例
    题目:
    某数据处理软件需要增加一个图表复制功能。在图表对象(DataChart)中包含一个数据集对象(DataSet)。数据集对象用于封装要显示的数据,用户可以通过界面上的复制按钮将该图表复制一份,复制后,即可得到新的图表对象,然后可以修改新图表的编号、颜色、数据。试用原型模式设计软件实现深克隆。

DataChart 类包含一个 DataSet 对象,在复制 DataChart 对象的同时将

复制 DataSet 对象,因此需要使用深克隆技术,可使用流来实现深克隆。其中Serializable是java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。故我们实现这个接口即可使用流来实现深克隆

三.原型管理器

原型管理器实现

原型管理器(Prototype Manager)是将多个原型对象存储在一个集合中供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象, 如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得。 在原型管理器中针对抽象原型类进行编程,以便扩展。 其结构如图所示:

其中原型管理器ProtptypeManager类的实现代码如下

复制代码
package prototype_pattern;

import java.util.Hashtable;

/**
 * @author Cnc_hzf
 * @date 2022/4/22 15:00
 */
public class PrototypeManager {
    private Hashtable prototypeTable = new Hashtable(); // 使用Hashtable存储原型对象
    public PrototypeManager() {
        prototypeTable.put("A", new ConcretePrototypeA());
        prototypeTable.put("B", new ConcretePrototypeB());
    }
    public void add(String key, Prototype prototype) {
        prototypeTable.put(key, prototype);
    }
    public Prototype get(String key) {
        Prototype clone = ((Prototype) prototypeTable.get(key)).clone(); // 通过克隆方法创建新对象
        return clone;
    }
}

在实际开发中可以将PrototypeManger设计为单例类,确保系统中有且仅有一个PrototypeManager对象,这样既有利于节省系统资源,还可以更好地对原型管理器对象进行控制。

原型管理器应用举例

问题描述:

某公司需要创建一个公文管理器,公文管理器中需要提供一个集合对象来存储一些公文模板,用户可以通过复制这些模板快速的创建新的公文,试使用带有原型管理器的原型模式来设计该公文管理器并使用Java代码编程模拟。

其中,OfficialDocument (抽象公文类)充当抽象原型类,其子类 FAR(Feasibility Analysis

Report,可行性分析报告)和 SRS(Software Requirements Specification,软件需求规格说明书)充当具体原型类,PrototypeManager 充当原型管理器。

相关推荐
num_killer3 小时前
小白的Langchain学习
java·python·学习·langchain
期待のcode4 小时前
Java虚拟机的运行模式
java·开发语言·jvm
程序员老徐4 小时前
Tomcat源码分析三(Tomcat请求源码分析)
java·tomcat
a程序小傲4 小时前
京东Java面试被问:动态规划的状态压缩和优化技巧
java·开发语言·mysql·算法·adb·postgresql·深度优先
仙俊红4 小时前
spring的IoC(控制反转)面试题
java·后端·spring
阿湯哥4 小时前
AgentScope Java 集成 Spring AI Alibaba Workflow 完整指南
java·人工智能·spring
小楼v4 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地4 小时前
NIO的三个组件解决三个问题
java·后端·nio
czlczl200209255 小时前
Guava Cache 原理与实战
java·后端·spring
yangminlei5 小时前
Spring 事务探秘:核心机制与应用场景解析
java·spring boot