当前位置: 首页 > article >正文

漫谈设计模式 [4]:原型模式

引导性开场

菜鸟:老鸟,我最近在做一个项目,需要创建很多相似的对象,但每次都要写很多重复的代码,感到有点头疼。有没有什么方法可以简化这个过程?

老鸟:这个问题很常见,其实有一个设计模式叫做“原型模式”可以帮助你解决这个问题。你想知道更多吗?

菜鸟:当然,听起来很有意思!

渐进式介绍概念

老鸟:好,我们先从一个简单的例子开始。你有没有买过外卖?

菜鸟:当然有啊。

老鸟:那你有没有注意到,每次你点的餐都差不多,但还是需要重复选择和确认?

菜鸟:是的,每次都要点很多相似的选项,有点烦。

老鸟:原型模式就像是保存了一份你常点餐的菜单模板,每次点餐的时候,只需要复制这个模板,再根据需要进行微调。这样就省去了重复选择的麻烦。

菜鸟:哦,明白了,那在编程中怎么实现呢?

Python代码示例,逐步展开

老鸟:我们用Python来实现一个简单的例子。假设我们有一个Person类。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'{self.name}, {self.age} years old'

菜鸟:这个类很简单,就是一个人的信息。

老鸟:对,现在我们每次都需要创建不同的Person对象,例如:

person1 = Person('Alice', 30)
person2 = Person('Bob', 25)

菜鸟:对,这样每次都要重新创建对象。

老鸟:现在我们引入原型模式,通过复制现有的对象来创建新的对象。我们可以给Person类添加一个clone方法。

import copy

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'{self.name}, {self.age} years old'

    def clone(self):
        return copy.deepcopy(self)

菜鸟:这个clone方法是用来复制对象的?

老鸟:对的,现在我们可以这样创建新的对象:

person1 = Person('Alice', 30)
person2 = person1.clone()
person2.name = 'Bob'
person2.age = 25

print(person1)  # Alice, 30 years old
print(person2)  # Bob, 25 years old

菜鸟:哇,这样就省去了重复创建对象的麻烦!

问题与反思

菜鸟:那如果没有原型模式,我是不是只能每次都手动创建对象?

老鸟:是的,手动创建不仅麻烦,而且容易出错。原型模式通过复制现有对象,确保了对象的一致性和简化了代码。

优势与适用场景

老鸟:原型模式的优势在于它可以很方便地创建复杂对象的副本,节省了初始化的时间和成本。适用于以下场景:

  1. 创建对象的过程比较复杂。
  2. 想要避免重复代码。
  3. 需要创建对象的副本并进行微调。

菜鸟:听起来很实用,那有现实生活中的例子吗?

老鸟:比如,你在绘图软件中创建了一个复杂的图形模板,每次需要用这个模板的时候,只需要复制一份,再进行修改,而不是重新创建。

常见误区与优化建议

菜鸟:那使用原型模式会有什么误区吗?

老鸟:常见的误区是没有深拷贝,导致修改副本时影响到原对象。要确保使用deepcopy来避免这个问题。另外,要注意对象中是否有无法复制的资源,如文件句柄或数据库连接。

菜鸟:明白了,我会注意这些问题的。

总结与延伸阅读

老鸟:今天我们学习了原型模式,它通过复制现有对象来创建新的对象,避免了重复代码,简化了对象的创建过程。你可以进一步阅读《设计模式:可复用面向对象软件的基础》这本书,了解更多设计模式。

菜鸟:谢谢老鸟,我会去看的!下一步我应该学什么设计模式呢?

老鸟:你可以学习单例模式和工厂模式,它们也是很实用的设计模式。

菜鸟:好的,非常感谢!


http://www.kler.cn/a/301221.html

相关文章:

  • mysql 的乐观锁和 mvcc 是一回事吗
  • Django5 2024全栈开发指南(二):Django项目配置详解
  • 数据处理与统计分析——05-Pandas中DataFrame的方法、属性、索引等一系列操作
  • 父组件提交时让各自的子组件验证表格是否填写完整
  • Ubuntu22.04基于ROS2-Humble安装moveit2教程(亲测)
  • 深度解读混合专家模型(MoE):算法、演变与原理
  • go-map系统学习
  • livox mid360不使用ros接收雷达数据
  • StreamPark集成k8s运行Flink
  • busybox移植:全能脚本版
  • 在亚马逊云科技上利用Graviton4代芯片构建高性能Java应用(下篇)
  • 3.Kubernetes资源对象之pod
  • 828华为云征文|华为云Flexus X实例docker部署最新版禅道构建属于自己的项目管理平台
  • 文心智能体应用:美国旅游助手的诞生
  • 【进展报告】9.9-9.12
  • Cargo 入门
  • 远程控制软件有哪些?不多,给你奉上这6款神仙软件
  • nodeJS学习笔记——包npm(2)
  • vue3利用ref操作dom元素
  • MySQL 的关键字
  • 高级 ECharts 技巧:自定义图表主题与样式
  • 详解Redis的AOF持久化方式以及aof日志重写配置以及对redis中的GEO地理位置数据类型命令的应用示例
  • 2023下半年软考网络规划
  • 【信号】信号的保存
  • ffmpeg面向对象-rtsp拉流相关对象
  • 为什么不写注释?写“为什么不”注释?