【原型模式】详解

一.概念

原型模式是一种创建型设计模式,它的主要思想是通过复制现有对象来创建新对象,而不是通过实例化一个类来创建。在原型模式中,我们称被复制的对象为原型(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 充当原型管理器。

相关推荐
小小深16 分钟前
了解JVM
java·jvm
Sunlight_77722 分钟前
第五章 SQLite数据库:1、SQLite 基础语法及使用案例
java·linux·服务器·jvm·数据库·tcp/ip·sqlite
JhonKI32 分钟前
【从零实现高并发内存池】内存池整体框架设计 及 thread cache实现
java·redis·缓存
何似在人间57539 分钟前
SpringAI+DeepSeek大模型应用开发——4 对话机器人
java·机器人·大模型应用开发·spring ai
-曾牛1 小时前
【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini,Spring Boot整合实战!| 附源码
java·开发语言·人工智能·spring boot·ai·chatgpt
kfepiza1 小时前
HttpSessionListener 的用法笔记250417
java·笔记·servlet·tomcat
冬天vs不冷1 小时前
SpringBoot条件注解全解析:核心作用与使用场景详解
java·spring boot·python
百锦再2 小时前
Android Studio 实现自定义全局悬浮按钮
android·java·ide·app·android studio·安卓
百锦再2 小时前
Android Studio 项目文件夹结构详解
android·java·ide·ios·app·android studio·idea
阿达King哥2 小时前
Java虚拟机(JVM)平台无关?相关?
java·jvm