专栏首页Python爬虫实战设计模式:原型模式

设计模式:原型模式

系列文章回顾

┣ 设计模式:简单工厂模式

┣ 设计模式:工厂方法模式

┣ 设计模式:抽象工厂模式

┣ 设计模式:单例模式

┣ 设计模式:建造者模式

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...

本文分享自微信公众号 - C与Python实战(CPythonPractice),作者:CPython

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式:工厂方法模式

    工厂方法(Factory Method)模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)...

    王强
  • Python数据类型之字典(上)

    之前系列文章介绍了Python简单数据类型和序列数据类型,本文来学习一种新的映射数据类型:字典。

    王强
  • Python数据类型之数字类型

    输入1就会显示1,我们怎么知道1就是整数类型呢?在Python里面有一个type()函数,它能告诉我们所代表的类型。

    王强
  • 正则表达式详解

    正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。比如,正则表达...

    IT人一直在路上
  • Vue3有哪些不向下兼容的改变

    作为技术人员,随时保持技术同步是很重要的事情。虽然Vue3已经发布很长时间了,现在开始保持更新也还不晚。新项目可以拿来练练手XD,老项目就不建议升级了。本篇文章...

    coder_koala
  • Laravel 项目中编写 Vue 组件

    新安装的 Laravel 应用在 resources/js/components 目录默认包含一个 ExampleComponent.vue Vue 组件。 ...

    hedeqiang
  • centos集群下的ssh免密登录

    然后给每台机器设置hostname,刚刚在配置文件里写的什么名字现在就设置什么名字,名字要和ip对应

    许喜朝
  • cockpit 设置端口;设置多端口监听;

    https://cockpit-project.org/guide/133/listen.html 

    xuyaowen
  • Vue2.0 定制一款属于自己的音乐 WebApp

    本次的系列博文的知识点讲解和代码,主要是来自于 黄轶 在慕课网的 Vue 2.0 高级实战-开发移动端音乐WebApp 课程,由个人总结并编写,其代码及知识点...

    Nian糕
  • 5个要点,决定你的交互设计是否成功!

    交互设计(Interaction Design):定义、设计人造系统的行为的设计领域。人造物,即人工制成物品,例如,软件、移动设备、人造环境、服务、可佩带装置以...

    BestSDK

扫码关注云+社区

领取腾讯云代金券