设计模式-原型模式详解

文章目录

  • 前言
  • 理论基础
    • 1. 原型模式定义
    • 2. 原型模式角色
    • 3. 原型模式工作过程
    • 4. 原型模式的优缺点
  • 实战应用
    • 1. 原型模式适用场景
    • 2. 原型模式实现步骤
    • 3. 原型模式与单例模式的区别
  • 原型模式的变体
    • 1. 带有原型管理器的原型模式
    • 2. 懒汉式单例模式的原型模式实现
    • 3. 细粒度原型模式
  • 总结

前言

  • 简介设计模式
  • 设计模式是在软件开发中常见问题的解决方案,它们是经过实践和经验总结出来的可重用的设计思想和解决方案。设计模式通过提供通用的架构、原则和指导,帮助开发人员更有效地编写高质量的代码。
    设计模式分为三个主要类别:
  1. 创建型模式:关注对象的创建过程,包括如何实例化对象,隐藏对象的创建细节以及对象的复制和克隆。
  2. 结构型模式:关注对象和类的组合方式,以实现更大结构的目标,例如类之间的关系。
  3. 行为型模式:关注类和对象间的交互和通信方式,以实现更好的协作和控制。
  • 原型模式简介
    原型模式是创建型模式的一种,它关注对象的复制和克隆。在某些情况下,通过传统的实例化方式创建新对象可能会非常昂贵或复杂。这时,原型模式提供了一种替代方法,通过克隆已有的对象来创建新对象,从而避免了昂贵的初始化过程。

原型模式通过使用克隆方法来生成新对象,可以节省资源和时间,并提高对象创建的效率。它适用于需要创建大量相似对象的场景,同时也具有良好的扩展性,可以根据需要通过继承和重写克隆方法来实现自定义的克隆逻辑。

总结起来,原型模式是一种通过克隆现有对象来创建新对象的设计模式。它提供了一种灵活、高效的对象创建方式,可以在某些场景下显著提高代码的复用性和可维护性。
在这里插入图片描述

理论基础

1. 原型模式定义

原型模式是一种创建型设计模式,它允许通过克隆现有对象来创建新对象,而无需依赖于传统的实例化过程。该模式通过复制现有对象的属性和状态,创建新的独立对象,并且可以根据需要修改其特定属性。

在原型模式中,我们定义一个抽象原型类,其中包含一个用于克隆对象的抽象方法。具体原型类则继承自抽象原型类,并实现了克隆方法,以便返回自身的克隆副本。客户端代码使用具体原型类的实例,并调用其克隆方法来创建新的对象。

原型模式的关键思想是通过已存在的对象来创建新的对象,而不是从头开始进行全新的实例化过程。通过克隆现有对象,可以避免重复的初始化工作和资源消耗,提高对象创建的效率。同时,原型模式也使得对象的创建更加灵活,可以根据需要进行修改和定制。

2. 原型模式角色

  • 抽象原型类
  • 具体原型类
  • 客户端

3. 原型模式工作过程

4. 原型模式的优缺点

实战应用

1. 原型模式适用场景

  • 对象初始化过程耗时较多
  • 类初始化需要消耗很多资源
  • 通过new的方式创建对象比较复杂
  • 需要避免使用类的子类来进行初始化配置

2. 原型模式实现步骤

  • 创建抽象原型类
  • 创建具体原型类
  • 创建客户端类

3. 原型模式与单例模式的区别

原型模式的变体

1. 带有原型管理器的原型模式

  • 带有原型管理器的原型模式:
    带有原型管理器的原型模式是对原型模式的扩展,它引入了一个原型管理器(Prototype Manager)来集中管理原型对象。原型管理器充当一个注册表,用于存储和获取各种原型对象。

这种变体的原型模式可以更方便地创建和管理多个不同类型的原型对象。客户端可以通过原型管理器获取所需的原型对象,而不需要自己显式地调用克隆方法。原型管理器可以在内部维护一个原型对象的集合,并根据需要进行复制和返回。

  • 带有原型管理器的原型模式代码实现:
import java.util.HashMap;
import java.util.Map;

// 原型接口
interface Prototype {
    Prototype clone();
}

// 具体原型类 A
class ConcretePrototypeA implements Prototype {
    private String name;

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

    public String getName() {
        return name;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototypeA(this.name);
    }
}

// 具体原型类 B
class ConcretePrototypeB implements Prototype {
    private int number;

    public ConcretePrototypeB(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototypeB(this.number);
    }
}

// 原型管理器
class PrototypeManager {
    private Map<String, Prototype> prototypes;

    public PrototypeManager() {
        prototypes = new HashMap<>();
    }

    public void registerPrototype(String key, Prototype prototype) {
        prototypes.put(key, prototype);
    }

    public Prototype getPrototype(String key) {
        Prototype prototype = prototypes.get(key);
        if (prototype != null) {
            return prototype.clone();
        }
        return null;
    }
}

// 客户端
public class Main {
    public static void main(String[] args) {
        PrototypeManager manager = new PrototypeManager();
        manager.registerPrototype("A", new ConcretePrototypeA("Prototype A"));
        manager.registerPrototype("B", new ConcretePrototypeB(10));

        Prototype prototypeA = manager.getPrototype("A");
        if (prototypeA != null) {
            System.out.println("Clone A: " + ((ConcretePrototypeA) prototypeA).getName());
        }

        Prototype prototypeB = manager.getPrototype("B");
        if (prototypeB != null) {
            System.out.println("Clone B: " + ((ConcretePrototypeB) prototypeB).getNumber());
        }
    }
}

2. 懒汉式单例模式的原型模式实现

  • 懒汉式单例模式的原型模式:
    懒汉式单例模式是一种常见的单例模式实现方式,它延迟实例化单例对象,直到第一次使用时才创建。将懒汉式单例模式与原型模式结合起来,可以实现一种延迟加载并复用实例的模式。

在这种变体的原型模式中,单例对象充当原型对象,当客户端第一次请求获取实例时,会通过克隆来获得对象的副本,并将其作为单例对象返回。之后,每次请求都将返回这个已存在的副本,避免了重复的创建和初始化过程。

这种实现方式结合了懒加载和对象的复用,可以在需要的时候动态创建新对象并缓存起来,提高了系统的性能和资源利用率。

  • 懒汉式单例模式的原型模式代码实现:
// 单例类
class Singleton {
    private static Singleton instance;

    // 私有构造函数
    private Singleton() {
        System.out.println("Singleton instance created.");
    }

    // 获取单例对象
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    // 克隆方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Cannot clone a singleton object.");
    }
}

// 客户端
public class Main {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        System.out.println("Singleton 1: " + singleton1);
        System.out.println("Singleton 2: " + singleton2);

        // 尝试克隆单例对象
        try {
            Singleton clone = (Singleton) singleton1.clone();
            System.out.println("Clone: " + clone);
        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }
    }
}

3. 细粒度原型模式

  • 细粒度原型模式:
    细粒度原型模式是指将一个复杂对象拆分成多个部分,并为每个部分创建对应的原型对象。这样,在需要使用某个部分时,只需要克隆该部分的原型对象即可,而不需要克隆整个复杂对象。

细粒度原型模式可以提高系统的灵活性和效率。它允许客户端选择需要的部分进行克隆,而不需要克隆整个对象。同时,当某个部分发生变化时,只需要修改对应的原型对象,而不需要重新创建整个对象。

这种模式适用于那些由多个组件或模块组成的复杂对象。通过细粒度的原型对象,可以更加灵活地构建和修改复杂对象的组成部分,减少了代码的重复和耦合度。

  • 细粒度原型模式代码
// 原型接口
interface Prototype {
    Prototype clone();
}

// 具体原型类 A
class ConcretePrototypeA implements Prototype {
    private String name;

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

    public String getName() {
        return name;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototypeA(this.name);
    }
}

// 具体原型类 B
class ConcretePrototypeB implements Prototype {
    private int number;

    public ConcretePrototypeB(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototypeB(this.number);
    }
}

// 客户端
public class Main {
    public static void main(String[] args) {
        Prototype prototypeA = new ConcretePrototypeA("Prototype A");
        Prototype cloneA = prototypeA.clone();
        if (cloneA instanceof ConcretePrototypeA) {
            System.out.println("Clone A: " + ((ConcretePrototypeA) cloneA).getName());
        }

        Prototype prototypeB = new ConcretePrototypeB(10);
        Prototype cloneB = prototypeB.clone();
        if (cloneB instanceof ConcretePrototypeB) {
            System.out.println("Clone B: " + ((ConcretePrototypeB) cloneB).getNumber());
        }
    }
}

总结

  • 原型模式使用总结
  • 原型模式对于软件开发的重要性
// 抽象原型类
abstract class Prototype implements Cloneable {
    public abstract Prototype clone();
}

// 具体原型类
class ConcretePrototype extends Prototype {
    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype();
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();
        // 进行操作
    }
}

以上代码展示了原型模式的简单实现,其中抽象原型类定义了一个抽象方法clone,在具体原型类中实现了这个方法,并通过调用super.clone()方法进行对象的克隆。在客户端中,可以创建一个原型对象并进行克隆,从而得到一个新的对象进行操作。

原型模式适用于需要创建大量相似对象的场景,通过克隆已有对象来提高效率。它简化了对象的创建过程,减少了重复的初始化操作。同时,原型模式也具有良好的可扩展性,可以通过继承和重写clone方法来实现自定义的克隆逻辑。

总的来说,原型模式是一种简单而实用的设计模式,在软件开发中具有广泛的应用价值。通过合理地运用原型模式,可以提高代码的复用性、可维护性和灵活性,从而提高软件开发的效率和质量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100175.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统架构技能之设计模式-抽象工厂模式

一、上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式。并且分析了每种模式的应用场景和一些优缺点&#xff0c;我们现在来回顾一下&#xff1a; 简单工厂模式&#xff1a;一个工厂负责所有类型对象的创建&#xff0c;不支持无缝的新增新的类型对象的创建。 工厂模式&…

JVM面试核心点

一、JDK体系 二、JVM体系 三、JVM内存模型 public class Math {public static final int data 666;public static UserEntity user new UserEntity();public int compute() { // 一个方法对应一块栈帧内存区域int a 1;int b 2;int c (ab)*10;return c;}public static voi…

Angular安全专辑之三 —— 授权绕过,利用漏洞控制管理员账户

这篇文章是针对实际项目中所出现的问题所做的一个总结。简单来说&#xff0c;就是授权绕过问题&#xff0c;管理员帐户被错误的接管。 详细情况是这样的&#xff0c;我们的项目中通常都会有用户身份验证功能&#xff0c;不同的用户拥有不同的权限。相对来说管理员账户所对应的…

openGauss学习笔记-57 openGauss 高级特性-并行查询

文章目录 openGauss学习笔记-57 openGauss 高级特性-并行查询57.1 适用场景与限制57.2 资源对SMP性能的影响57.3 其他因素对SMP性能的影响57.4 配置步骤 openGauss学习笔记-57 openGauss 高级特性-并行查询 openGauss的SMP并行技术是一种利用计算机多核CPU架构来实现多线程并行…

2023-9-2 Prim算法求最小生成树

题目链接&#xff1a;Prim算法求最小生成树 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 510, INF 0x3f3f3f3f;int n, m; int g[N][N]; int dist[N]; bool st[N];int prim() {memset(dist, 0x3f, size…

Qt应用开发(基础篇)——进度对话框 QProgressDialog

一、前言 QProgressDialog类继承于QDialog&#xff0c;是Qt设计用来反馈进度的对话框。 对话框QDialog QProgressDialog提供了一个进度条&#xff0c;表示当前程序的某操作的执行进度&#xff0c;让用户知道操作依旧在激活状态&#xff0c;配合按钮&#xff0c;用户就可以随时终…

qt文件操作

对话框练习 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//字体按钮 void Widget::on_ztbtn_clicked() {//调用QFontDia…

stable diffusion实践操作-常见lora模型介绍

本文专门开一节写Lora相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 模型分两种&#xff0c;一种是sd大模型&#xff0c;一种是类似Lora的小模型 国内的是&#xff1a;https://www.liblibai.com 国外的是&#xff1a;https:/…

TiDB Serverless Branching:通过数据库分支简化应用开发流程

2023 年 7 月 10 日&#xff0c;TiDB Serverless 正式商用。这是一个完全托管的数据库服务平台&#xff08;DBaaS&#xff09;&#xff0c;提供灵活的集群配置和基于用量的付费模式。紧随其后&#xff0c;TiDB Serverless Branching 的测试版也发布了。 TiDB Serverless Branc…

代码随想录算法训练营第二十四天|理论基础 77. 组合

理论基础 其实在讲解二叉树的时候&#xff0c;就给大家介绍过回溯&#xff0c;这次正式开启回溯算法&#xff0c;大家可以先看视频&#xff0c;对回溯算法有一个整体的了解。 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学透回溯算法&#xff08;理论篇…

Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录

Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录 目录 Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录 一、简单介绍 二、OKHttp 4.xx 的 SDK 封装 aar 给 Unity 的使用注意 三、附录 OKHttp 的…

【记录】USSOCOM Urban3D 数据集读取与处理

Urban3D数据集内容简介 Urban3D数据集图像为正摄RGB影像&#xff0c;分辨率为50cm。 从SpaceNet上使用aws下载数据&#xff0c;文件夹结构为&#xff1a; |- 01-Provisional_Train|- GT|- GT中包含GTC&#xff0c;GTI&#xff0c;GTL.tif文件&#xff0c;GTL为ground truth b…

openssh---Windows下git安装配置gitlab

安装openssh 1. 专业版Win10/11默认自带&#xff0c;可以查看是否开启 1. Get-WindowsCapability -Online | Where-Object Name -like OpenSSH* 2. Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 3. Add-WindowsCapability -Online -Name OpenSSH.Serve…

Excel显示此值与此单元格定义的数据验证限制不匹配怎么办?

总结&#xff1a;1、在编辑excel文档的时候&#xff0c;弹出此时预测单元格定义的数据验证&#xff0c;限制不匹配的提示。2、这是我们点击菜单来的数据菜单。3、然后点击数据工具栏的数据验证下拉按钮。4、在弹出的菜单中选择数据验证的菜单项。5、然后在打开的窗口中点击左下…

10个免费PPT下载资源网站分享

PPT超级市场https://pptsupermarket.com/ PPT超级市场是一个完全免费的PPT模板下载网站&#xff0c;不需要注册登录&#xff0c;点击下载就能直接使用。 叮当设计https://www.dingdangsheji.com/ 叮当设计是一个完全免费的PPT模板下载网站&#xff0c;每一套PPT的质量都很高。除…

Docker构建Springboot项目,并发布测试

把SpringBoot项目打包成Docker镜像有两种方案&#xff1a; 全自动化&#xff1a;先打好docker镜像仓库&#xff0c;然后在项目的maven配置中配置好仓库的地址&#xff0c;在项目里配置好Dockerfile文件&#xff0c;这样可以直接在idea中打包好后自动上传到镜像仓库&#xff0c…

VUE环境下 CSS3+JS 实现发牌 翻牌

创建牌容器&#xff08;关键点&#xff1a;overflow&#xff1a;hidden&#xff09;&#xff1a; <div class"popup-box"></div> .popup-box {position: absolute;width: 100vw;height: 100vh;top: 0px;left: 0;overflow: hidden; } 创建每一张牌《固…

透过源码理解Flutter InheritedWidget

InheritedWidget的核心是保存值和保存使用这个值的widget&#xff0c;通过对比值的变化&#xff0c;来决定是否要通知那些使用了这个值的widget更新自身。 1 updateShouldNotify和notifyClients InheritedWidget通过updateShouldNotify函数控制依赖其的子组件是否在Inherited…

4.22 TCP 四次挥手,可以变成三次吗?

目录 为什么 TCP 挥手需要四次呢&#xff1f; 粗暴关闭 vs 优雅关闭 close函数 shotdown函数 什么情况会出现三次挥手&#xff1f; 什么是 TCP 延迟确认机制&#xff1f; TCP 序列号和确认号是如何变化的&#xff1f; 在一些情况下&#xff0c; TCP 四次挥手是可以变成 T…

FFmpeg支持多线程编码并保存mp4文件示例

之前介绍的示例&#xff1a; (1).https://blog.csdn.net/fengbingchun/article/details/132129988 中对编码后数据保存成mp4 (2).https://blog.csdn.net/fengbingchun/article/details/132128885 中通过AVIOContext实现从内存读取数据 (3).https://blog.csdn.net/fengbingchun/…