C++设计模式_10_ Prototype 原型模式(小模式,不太常用)

Prototype 原型模式仍然属于"对象创建模式"模式的一种。前面两篇介绍的工厂方法模式和抽象工厂模式的流行程度要远大于Prototype 原型模式和builder构建器模式,后两种由于较为简单,介绍篇幅也会少一些。

文章目录

  • [1. 动机 (Motivation)](#1. 动机 (Motivation))
  • [2. 代码演示Prototype 原型模式](#2. 代码演示Prototype 原型模式)
    • [2.1 Prototype.cpp](#2.1 Prototype.cpp)
    • [2.2 ConcretePrototype.cpp](#2.2 ConcretePrototype.cpp)
    • [2.3 Client](#2.3 Client)
  • [3. 模式定义](#3. 模式定义)
  • [4. 结构](#4. 结构)
  • [5. 要点总结](#5. 要点总结)
  • [6. 其他参考](#6. 其他参考)

1. 动机 (Motivation)

  • 在软件系统中,经常面临着"某些结构复杂的对象"的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
  • 如何应对这种变化?如何向"客户程序(使用这些对象的程序)"隔离出"这些易变对象"从而使得"依赖这些易变对象的客户程序"不随着需求改变而改变?

与Factory Method工厂方法模式区别就在于"某些结构复杂的对象",利用深克隆将对象你想要的当前状态取出来,原型就可以实现传入的prototype状态是怎样就能深克隆一个出来,实现状态复杂对象的再现。

结构复杂的界定很难明确界定,使用Prototype 原型模式和Factory Method工厂方法模式的区别就是看是否Factory Method工厂方法模式可以很简便的创建对象,还是需要需要考虑对象复杂的中间状态,又希望保留该状态,如果是后者就使用Prototype 原型模式。实际使用原型模式的场景很少。

Prototype 原型模式解决的问题是与Factory Method工厂方法模式一模一样的,也是有一些细微不同,属于Factory Method工厂方法模式的变体。

2. 代码演示Prototype 原型模式

2.1 Prototype.cpp

C++设计模式_08_Factory Method工厂方法模式中可以看到Factory Method工厂方法对应的代码,Prototype 原型模式中将以下代码中的2个类合并起来。

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};


//工厂基类
class SplitterFactory{
public:
    virtual ISplitter* CreateSplitter()=0;
    virtual ~SplitterFactory(){}
};

变为以下形式:

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
    virtual ISplitter* CreateSplitter()=0;
};

并修改类的名字得到:

Prototype.cpp

cpp 复制代码
//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ISplitter* clone()=0; //通过克隆自己来创建对象
    
    virtual ~ISplitter(){}

};

2.2 ConcretePrototype.cpp

Factory Method工厂方法中FileSplitter2.cpp就变为以下形式:

ConcretePrototype.cpp

cpp 复制代码
//具体类
class BinarySplitter : public ISplitter{
public:
    virtual ISplitter* clone(){
        return new BinarySplitter(*this);
    }
};

class TxtSplitter: public ISplitter{
public:
    virtual ISplitter* clone(){
        return new TxtSplitter(*this);
    }
};

class PictureSplitter: public ISplitter{
public:
    virtual ISplitter* clone(){
        return new PictureSplitter(*this);
    }
};

class VideoSplitter: public ISplitter{
public:
    virtual ISplitter* clone(){
        return new VideoSplitter(*this);
    }
};

在C++中有着最成熟的克隆自己的方法就是拷贝构造函数,也就是上面的new TxtSplitter(*this),前提是你类的拷贝构造函数要写正确。

2.3 Client

Client也就是MainForm则变为:

cpp 复制代码
class MainForm : public Form
{
    ISplitter*  prototype;//原型对象

public:
    
    MainForm(ISplitter*  prototype){
        this->prototype=prototype;
    }
    
	void Button1_Click(){

		ISplitter * splitter=
            prototype->clone(); //克隆原型得到新对象
        
        splitter->split();
                
	}
};

有些人可能会想到将上面的splitter->split();变为删除 ISplitter * splitter=prototype->clone(); //克隆原型,变为prototype->split();,这是不对的,因为原型对象是供克隆的,真正使用的时候需要创建出新的对象,不能一直使用prototype原型对象。

以上即为Prototype 原型模式。

3. 模式定义

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

------《设计模式》GoF

"原型实例"就是在MainForm中的ISplitter* prototype;,这里的"拷贝"是深克隆。

4. 结构

上图是《设计模式》GoF中定义的Prototype 原型模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分,也就是下图中红框和蓝框框选的部分。

5. 要点总结

  • Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有"稳定的接口"
  • Prototype模式对于"如何创建易变类的实体对象"采用"原型克隆"的方法来做,它使得我们可以非常灵活地动态创建"拥有某些稳定接口"的新对象一-所需工作仅仅是注册一个新类的对象 (即原型),然后在任何需要的地方Clone。
  • Prototype模式中的Clone方法可以利用某些框架中的序列化来实现深拷贝。(其他语言中需要利用框架)

6. 其他参考

C++设计模式------原型模式

相关推荐
请你打开电视看看4 分钟前
观察者模式
java·观察者模式·设计模式
Mr.朱鹏7 分钟前
设计模式之策略模式-工作实战总结与实现
java·spring·设计模式·kafka·maven·策略模式·springbbot
深思慎考22 分钟前
计算机操作系统——进程控制(Linux)
linux·服务器·c++·c
春风十里不如你952733 分钟前
【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)
设计模式·组合模式
捕鲸叉40 分钟前
C++设计模式之组合模式实践原则
c++·设计模式·组合模式
阿熊不会编程1 小时前
【计网】自定义协议与序列化(一) —— Socket封装于服务器端改写
linux·开发语言·网络·c++·设计模式
春风十里不如你95271 小时前
【设计模式】【行为型模式(Behavioral Patterns)】之责任链模式(Chain of Responsibility Pattern)
java·设计模式·责任链模式
碧海蓝天20221 小时前
接上一主题,C++14中如何设计类似于std::any,使集合在C++中与Python一样支持任意数据?
开发语言·c++·python
醉颜凉1 小时前
计算(a+b)/c的值
java·c语言·数据结构·c++·算法
zl.rs2 小时前
对比C++,Rust在内存安全上做的努力
c++·安全·rust