设计模式:原型模式
时间:2022-07-25
本文章向大家介绍设计模式:原型模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
系列文章回顾
1 概述
原型模式使用原型实例指定创建对象的种类,并且通过拷贝原型对象创建新的对象。原型模式的关键点在于原型实例与实例的复制,实例的克隆分为深拷贝与浅拷贝。
- 浅拷贝:对于字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象与其副本引用同一对象。
- 深拷贝:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
原型模式使用的是深拷贝, 使用原型模式复制对象不会调用类的构造方法。
2 图解
01_Prototype
原型模式包含三种角色:
- Prototype(原型):定义用于复制现有实例来生成新实例的方法。
- ConcretePrototype(具体原型):负责实现复制现有实例并生成新实例的方法。
- Client(使用者):负责使用复制实例的方法生成新实例。
3 优缺点
优点:
- 性能提高,直接拷贝内存里内容比直接新建实例节省资源;
- 简化对象创建,避免了构造函数的约束,不受构造函数的限制直接复制对象;
- 可通过深克隆的方式保存对象的状态,可以辅助实现撤销操作。
缺点:
- 需要为每个类准备一个克隆方法,该方法位于类的内部,当对已有类进行改造时,需要修改原代码,违背了开闭原则;
- 在实现深拷贝时需要写较复杂的代码,如果对象之间存在多重嵌套引用时,为了实现深拷贝,每一层对象对应的类必须支持深拷贝,实现比较麻烦。
4 应用场景
- 资源优化场景:类初始化需要消耗非常多的资源,原型模式避免了此类消耗;
- 性能和安全要求的场景:通过new产生一个对象需要非常繁琐的数据准备或访问权限时,可以使用原型模式;
- 一个对象多个修改者的场景:一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以使用原型模式拷贝多个对象供调用者使用;
- 系统要保存对象的状态,而对象的状态变化很小。
5 实例
02_Prototype_UML
5.1 Python 实现
- prototype.py
#-*- coding: utf-8 -*-
'''
原型模式
'''
from copy import copy, deepcopy
class Prototype(object):
"""原型类"""
def __init__(self):
super(Prototype, self).__init__()
def clone(self):
pass
class ConcretePrototype1(Prototype):
"""具体原型类"""
def __init__(self):
print("Create ConcretePrototype1")
def clone(self):
print("Copy ConcretePrototype1...")
return deepcopy(self)
class ConcretePrototype2(Prototype):
"""具体原型类"""
def __init__(self):
print("Create ConcretePrototype2")
def clone(self):
print("Copy ConcretePrototype2...")
return deepcopy(self)
if __name__ == '__main__':
p1 = ConcretePrototype1()
cp1 = p1.clone()
p2 = ConcretePrototype2()
cp2 = p2.clone()
输出结果:
Create ConcretePrototype1
Copy ConcretePrototype1...
Create ConcretePrototype2
Copy ConcretePrototype2...
5.2 C++ 实现
- prototype.h
#ifndef PROTOTYPE_H
#define PROTOTYPE_H
#include <iostream>
using namespace std;
class Prototype
{
public:
virtual ~Prototype() {}
virtual Prototype* clone() const = 0;
protected:
Prototype() {}
};
class ConcretePrototype1 : public Prototype
{
public:
ConcretePrototype1() {
cout << "Create ConcretePrototype1." << endl;
}
ConcretePrototype1(const ConcretePrototype1& other) {
cout << "Copy ConcretePrototype1..." <<endl;
}
~ConcretePrototype1() {}
ConcretePrototype1* clone() const {
return new ConcretePrototype1(*this);
}
};
class ConcretePrototype2 : public Prototype
{
public:
ConcretePrototype2() {
cout << "Create ConcretePrototype2." << endl;
}
ConcretePrototype2(const ConcretePrototype2& other) {
cout << "Copy ConcretePrototype2..." <<endl;
}
~ConcretePrototype2() {}
ConcretePrototype2* clone() const {
return new ConcretePrototype2(*this);
}
};
#endif // PROTOTYPE_H
- main.cpp
#include <iostream>
#include "prototype.h"
using namespace std;
int main()
{
Prototype* p1 = new ConcretePrototype1();
Prototype* cp1 = p1->clone();
Prototype* p2 = new ConcretePrototype2();
Prototype* cp2 = p2->clone();
delete p1;
delete cp1;
delete p2;
delete cp2;
return 0;
}
输出结果:
Create ConcretePrototype1.
Copy ConcretePrototype1...
Create ConcretePrototype2.
Copy ConcretePrototype2...
- OpenCV3.2集成Android Studio2.2开发配置
- laravel中使用gulp打包发布前端部分
- Spring的编程式事务和声明式事务
- Java过滤器Filter的使用详解
- 基于积分图的二值图像膨胀算法实现
- Java监听器Listener的使用详解
- 图像各向异性滤波
- Python爬虫实战-抓取《盗墓笔记》所有章节及链接
- JSP 和 Servlet 的工作原理和生命周期
- Python OpenCV像素操作
- 别人在抢红包,而程序员在研究微信红包的算法实现
- C++模板类与Qt信号槽混用
- Python3.6+OpenCV3.3开发环境搭建
- 谷歌开源的大数据处理项目 Apache Beam
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- View的有效曝光监控(下)|ScrollView NestScrollView篇
- 聊聊AbstractProcessor和Java编译流程
- Okhttp如何开启的Http2.0
- PHP Execute Command Bypass Disable_functions
- 聊聊Android编译流程
- Android组件化问题思考
- 最近面试碰到的两道算法题|面试相关
- Thread也会OOM吗?
- RoundCube Webmail邮件正文存储型XSS(CVE-2015-1433)
- 再谈Android Lint
- Android DiffUtil 封装|深拷贝
- [CVE-2014-8959] phpmyadmin任意文件包含漏洞分析
- Android 统计页面渲染时长
- Transform和Task之间有关?| Gradle
- user.ini文件构成的PHP后门