设计模式-原型模式详解

news2024/11/17 22:25:03

文章目录

  • 前言
  • 理论基础
    • 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方法来实现自定义的克隆逻辑。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

敏捷开发要点

敏捷开发是一种以人为核心&#xff0c;迭代、增量式的软件开发方法。它强调团队成员的自我管理、面对变化时的快速适应能力&#xff0c;以及持续的沟通和协作。 以下是敏捷开发的几个要点&#xff1a; 敏捷宣言&#xff1a;敏捷开发遵循敏捷宣言&#xff0c;其中包括四个价值声…

Java单元测试及常用语句 | 京东物流技术团队

1 前言 编写Java单元测试用例&#xff0c;即把一段复杂的代码拆解成一系列简单的单元测试用例&#xff0c;并且无需启动服务&#xff0c;在短时间内测试代码中的处理逻辑。写好Java单元测试用例&#xff0c;其实就是把“复杂问题简单化&#xff0c;建单问题深入化“。在编写的…

stm32CubeMX HAL W5500芯片介绍 第一章

W5500芯片介绍 文章目录 W5500芯片介绍简单简绍以太网以太网分五层&#xff1a;第一层物理层&#xff1a;第二层&#xff1a;数据链路层&#xff1a;第三层&#xff1a;网络层&#xff1a;第四层&#xff1a;传输层&#xff1a;第五层&#xff1a;应用层&#xff1a;以太网应用…

redis面试题二

redis如何处理已过期的元素 常见的过期策略 定时删除&#xff1a;给每个键值设置一个定时删除的事件&#xff0c;比如有一个key值今天5点过期&#xff0c;那么设置一个事件5点钟去执行&#xff0c;把它数据给删除掉&#xff08;优点&#xff1a;可以及时利用内存及时清除无效数…

《存储IO路径》专题:IO块设备的创建

今天我们来一起学习一下Linux块设备层。它就像是一位大厨&#xff0c;为我们准备各种数据的饕餮盛宴。这个大厨非常厉害&#xff0c;不仅能够读取和写入数据&#xff0c;还能对数据进行各种复杂的操作&#xff0c;比如切割、合并、复制等等。那么&#xff0c;块设备层是如何实现…

C#-抽象类与接口

文章目录 一、抽象类和接口总结总结补充说明主要区别 二、抽象类2.1 抽象类概述与声明2.2 抽象方法2.3 抽象类与抽象方法的使用 三、接口3.1 接口概述概述特征声明示例 3.2 接口的实现和继承说明示例 3.3 显式接口成员实现说明注意示例 一、抽象类和接口总结 总结 抽象类和接…

k8s使用ECK(2.4)形式部署elasticsearch+kibana-http协议

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、准备elasticsearch-cluster.yaml二、部署并测试总结 前言 之前写了eck2.4部署eskibana&#xff0c;默认的话是https协议的&#xff0c;这里写一个使用http…

【docker】docker的一些常用命令-------从小白到大神之路之学习运维第92天

目录 一、安装docker-ce 1、从阿里云下载docker-cer.epo源 2、下载部分依赖 3、安装docker 二、启用docker 1、启动docker和不启动查看docker version 2、启动服务查看docker version 有什么区别&#xff1f;看到了吗&#xff1f; 3、看看docker启动后的镜像仓库都有什…

解密Spring MVC异常处理:从局部到全局,打造稳固系统的关键步骤

&#x1f600;前言 在现代软件开发中&#xff0c;异常处理是不可或缺的一部分&#xff0c;它能够有效地提高系统的稳定性和健壮性。在Spring MVC框架中&#xff0c;异常处理机制起着至关重要的作用&#xff0c;它允许开发者在程序运行过程中捕获、处理和报告异常&#xff0c;从…

26 Linux高级篇-Linux面试题

26 Linux高级篇-Linux面试题 文章目录 26 Linux高级篇-Linux面试题1.分析日志t.txt(访问量)&#xff0c;将各个ip地址截取&#xff0c;并统计出现次数&#xff0c;并按从大到小排序(腾讯)2.统计连接到服务器的各个ip情况&#xff0c;并按连接数从大到小排序(腾讯)3.如忘记了mys…

历时3天的springboot+vue打包成jar包

有人说问什么打包花了三天&#xff0c;里面的坑很多&#xff0c;我就先不叙述太多&#xff0c;直接说我搞了三天得出来的最后解决方案&#xff0c;不一定适合每一个人&#xff01;! # 前端 # 修改prod.env.js文件下的内容&#xff0c;把里面的 BASE_API 修改为和dev.env.js文件…

[管理与领导-63]:IT基层管理者 - 潜技能 - 1 - 职场中的陷阱 - 看清楚职场中的霸凌现象

目录 前言&#xff1a; 1&#xff1a;打击自尊心 2&#xff1a;孤立他人 3&#xff1a;恶意针对 4&#xff1a;当众羞辱 5&#xff1a;持续性否定 前言&#xff1a; 职场中&#xff0c;什么样的人都有。 害人之心不可有&#xff0c;防人之心不可无。 前者教人从善&…

顺序栈(数组形式)的实现

&#x1f308;什么是栈&#xff1f; 1.抽象化具象&#xff1a;可以理解为一个细长的乒乓球筒&#xff0c;一端封闭&#xff0c;放球只能从另一端放入球&#xff0c;取出球时也只能从该端取出。先进的球最后出&#xff0c;后进的球最先出。 2.定义&#xff1a;栈是一种线性数据…

【C++】map/multimap容器

1.map基本概念 2.map构造和赋值 #include <iostream> using namespace std;//map容器 构造和赋值 #include<map>//遍历输出map容器 void printMap(const map<int, int>& m) {for (map<int, int>::const_iterator it m.begin(); it ! m.end(); it)…

Ubuntu学习---跟着绍发学linux课程记录(第一部分)

文章目录 1、启动、关闭、挂起、恢复&#xff08;电源&#xff09;2、更多虚拟机操作2.1 电源设置2.2 硬件参数设置2.3 状态栏2.4 全屏显示 3、快照与系统恢复4、桌面环境5、文件系统6、用户目录7、创建目录和文件8、命令行&#xff1a;文件列表ls 9、命令行&#xff1a;切换目…

分布式任务调度框架

分布式任务调度框架 学习为主 文章目录 分布式任务调度框架一、概念二、架构图三、任务调度的流程定时触发任务是如何实现的&#xff1f;&#xff1a;使用时间轮实现定时执行任务逻辑:3.1 对到达now时间后的任务&#xff08;超出now 5秒外)3.2 对到达now时间后的任务&#xff0…

从代码设计看 Glide 之生命周期(上)

欢迎关注我的其他平台账号&#xff1a; 掘金&#xff1a;0xforee 个人博客&#xff1a;0xforee’s blog 微信公众号&#xff1a; 上期我们探索了一个具备核心功能的图片加载库该怎么设计。这一期我们来看看如何给这个图片加载库关联生命周期管理。 欢迎关注本系列其他文章&…

PPPoE连接无法建立的排查和修复

嗨&#xff0c;亲爱的读者朋友们&#xff01;你是否曾经遇到过PPPoE连接无法建立的问题&#xff1f;今天我将为你详细解析排查和修复这个问题的步骤。 检查物理连接 首先&#xff0c;我们需要确保物理连接没有问题。请按照以下步骤进行检查&#xff1a; - 检查网线是否插好&…

vue训练场练习props和$emit,实现大写输入,小写输出。

场景&#xff1a; 在vue官网训练场&#xff0c;使用训练场中的组件。 仅作为练习笔记&#xff0c;仅供产考。 App.vue 组件代码 方式一&#xff1a;Watch监听 方式二&#xff1a;input绑定

安卓系列机型--软扩容“system分区扩容”操作步骤解析 增加系统分区大小

感兴趣的友友要区别扩容的概念。软扩容与硬扩容。硬扩容指拆解手机字库。更换大容量的字库来达到硬扩容。例如864硬扩容为8256等等。所谓的软扩容指的是将系统默认的系统分区大小修改分区表增大分区。例如原来系统分区默认2G。修改分区表为3G大小。意义在于可以刷写有些需要扩容…