C++ 设计模式----“对象创建“模式

news2024/11/26 23:46:58

“对象创建”模式

 通过“对象创建” 模式绕开new来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。

 典型模式

• Factory Method

• Abstract Factory

• Prototype

• Builder

Factory Method工厂方法

**动机(Motivation)**💡:

 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。

**问题思考(Consider)**🤔:

 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种**“封装机制”来避免客户程序和这种“具体对象创建工作”**的紧耦合?

(一)依赖具体类

FileSplitter1.cpp

class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};

class BinarySplitter : public ISplitter{
    void split(){
        // ...
    }
};

class TxtSplitter: public ISplitter{
    void split(){
        // ...
    }
};

class PictureSplitter: public ISplitter{
    void split(){
        // ...
    }
};

class VideoSplitter: public ISplitter{
    void split(){
        // ...
    }
};


MainForm1.cpp

#include"FileSplitter1.cpp"

class Form{
	
};
class TextBox;
class ProgressBar;
class ISplitter;

class MainForm : public Form
{
	TextBox* txtFilePath;
	TextBox* txtFileNumber;
	ProgressBar* progressBar;

public:
	void Button1_Click(){

		ISplitter * splitter= new BinarySplitter();//依赖具体类
        splitter->split();

	}
};

(二)多态new

ISplitterFactory.cpp

//抽象类
class ISplitter{
public:
    virtual void split()=0;
    virtual ~ISplitter(){}
};

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

FileSplitter2.cpp

#include"ISplitterFactory.cpp"

//具体类
class BinarySplitter : public ISplitter{
    void split(){
        // ...
    }
};

class TxtSplitter: public ISplitter{
    void split(){
        // ...
    }
};

class PictureSplitter: public ISplitter{
    void split(){
        // ...
    }
};

class VideoSplitter: public ISplitter{
    void split(){
        // ...
    }
};

//具体工厂
class BinarySplitterFactory: public SplitterFactory{
public:
    virtual ISplitter* CreateSplitter(){
        return new BinarySplitter();
    }
};

class TxtSplitterFactory: public SplitterFactory{
public:
    virtual ISplitter* CreateSplitter(){
        return new TxtSplitter();
    }
};

class PictureSplitterFactory: public SplitterFactory{
public:
    virtual ISplitter* CreateSplitter(){
        return new PictureSplitter();
    }
};

class VideoSplitterFactory: public SplitterFactory{
public:
    virtual ISplitter* CreateSplitter(){
        return new VideoSplitter();
    }
};


MainForm2.cpp

#include"ISplitterFactory.cpp"
class Form{
	
};
class TextBox;
class ProgressBar;

class MainForm : public Form
{
    SplitterFactory*  factory;//工厂
public:
    MainForm(SplitterFactory*  factory){
        this->factory=factory;
    }
    
	void Button1_Click(){

        
		ISplitter * splitter=factory->CreateSplitter(); //多态new
        splitter->split();

	}
};

FactoryMethod1.cpp

#include<iostream>
using namespace std;

class AbstractMonk {
public:
	virtual void ability() = 0;//技能
	virtual void petPhrase() = 0;//口头禅
	virtual ~AbstractMonk() {}
};

//和尚--孙悟空
class SunWuKong : public AbstractMonk {
public:
	void ability() {
		cout << "腾云驾雾,七十二般变化,有极高的悟性" << endl;
	}
	void petPhrase() {
		cout << "吃俺老孙一棒" << endl;
	}
};

//和尚--猪八戒
class ZhuBaJie : public AbstractMonk {
public:
	void ability() {
		cout << "唱小曲,三十六般变化,吞吃人参果" << endl;
	}
	void petPhrase() {
		cout << "猴哥!师父被妖怪抓走了!" << endl;
	}
};

//和尚--沙僧
class ShaSen : public AbstractMonk {
public:
	void ability() {
		cout << "和事佬,辅助战斗" << endl;
	}
	void petPhrase() {
		cout << "师傅放心,,大师兄会来救我们的" << endl;
	}
};

//和尚--唐僧
class TangSen : public AbstractMonk {
public:
	void ability() {
		cout << "念经诵佛,让猴哥头疼" << endl;
	}
	void petPhrase() {
		cout << "贫僧从东土大唐而来,前往西天拜佛求经" << endl;
	}
};

class AbstractFactory {
public:
	virtual AbstractMonk* createMonk() = 0;
	virtual ~AbstractFactory() {}
};

class SunWuKongFactory : public AbstractFactory {
public:
	AbstractMonk* createMonk() override{
		return new SunWuKong();
	}
	~SunWuKongFactory() {
		cout << "释放 SunWuKongFactory 类相关的内存资源" << endl;
	}
};

class ZhuBaJieFactory : public AbstractFactory {
public:
	AbstractMonk* createMonk() override {
		return new ZhuBaJie();
	}
	~ZhuBaJieFactory() {
		cout << "释放 ZhuBaJieFactory 类相关的内存资源" << endl;
	}
};

class ShaSenFactory : public AbstractFactory {
public:
	AbstractMonk* createMonk() override {
		return new ShaSen();
	}
	~ShaSenFactory() {
		cout << "释放 ShaSenFactory 类相关的内存资源" << endl;
	}
};

class TangSenFactory : public AbstractFactory {
public:
	AbstractMonk* createMonk() override {
		return new TangSen();
	}
	~TangSenFactory() {
		cout << "释放 TangSenFactory 类相关的内存资源" << endl;
	}
};
/*
	不论是和尚的基类,还是工厂类的基类,它们的虚函数可以是纯虚函数,
	也可以是非纯虚函数。这样的基类在设计模式中就可以称之为抽象类
	(此处的抽象类和 C++ 中对抽象类的定义有一点出入)。
*/
int main() {
	//创建取经团队: 孙悟空 猪八戒 沙僧 唐僧
	cout << "俺是齐天大圣,孙悟空" << endl;
	AbstractFactory* swkFactory = new SunWuKongFactory;
	AbstractMonk* swkObj = swkFactory->createMonk();
	cout << "技能:";
	swkObj->ability();
	cout << "口头禅:";
	swkObj->petPhrase();
	cout << endl;

	cout << "俺是天蓬元帅,猪八戒" << endl;
	AbstractFactory* zbjFactory = new ZhuBaJieFactory;
	AbstractMonk* zbjObj = zbjFactory->createMonk();
	cout << "技能:";
	zbjObj->ability();
	cout << "口头禅:";
	zbjObj->petPhrase();
	cout << endl;

	cout << "俺是卷帘大将,沙僧" << endl;
	AbstractFactory* ssFactory = new ShaSenFactory;
	AbstractMonk* ssObj = ssFactory->createMonk();
	cout << "技能:";
	ssObj->ability();
	cout << "口头禅:";
	ssObj->petPhrase();
	cout << endl;

	cout << "俺是金蝉子,法名玄奘,号三藏。" << endl;
	AbstractFactory* tsFactory = new TangSenFactory;
	AbstractMonk* tsObj = tsFactory->createMonk();
	cout << "技能:";
	tsObj->ability();
	cout << "口头禅:";
	tsObj->petPhrase();
	cout << endl;
	return 0;
}

在这里插入图片描述

FactoryMethod2.cpp

#include <iostream>
#include <string>

class Product
{
public:
    virtual ~Product() {}
    virtual std::string getName() = 0;
};

class ConcreteProductA : public Product
{
public:
    ~ConcreteProductA() {}
    std::string getName()
    {
        return "type A";
    }
};

class ConcreteProductB : public Product
{
public:
    ~ConcreteProductB() {}
    std::string getName()
    {
        return "type B";
    }
};

class Creator
{
public:
    virtual ~Creator() {}
    virtual Product* createProductA() = 0;
    virtual Product* createProductB() = 0;
    virtual void removeProduct(Product* product) = 0;
};

class ConcreteCreator : public Creator
{
public:
    ~ConcreteCreator() {}
    Product* createProductA(){
        return new ConcreteProductA();
    }

    Product* createProductB(){
        return new ConcreteProductB();
    }

    void removeProduct(Product* product){
        delete product;
    }
};

int main()
{
    Creator* creator = new ConcreteCreator();

    Product* p1 = creator->createProductA();
    std::cout << "Product: " << p1->getName() << std::endl;
    creator->removeProduct(p1);

    Product* p2 = creator->createProductB();
    std::cout << "Product: " << p2->getName() << std::endl;
    creator->removeProduct(p2);

    delete creator;
    return 0;
}

在这里插入图片描述

模式定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。

——《设计模式》GoF

结构(Structure)

在这里插入图片描述

要点总结

 Factory Method模式用于隔离类对象的使用者和具体类型之间的 耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导 致软件的脆弱。

 Factory Method模式通过面向对象的手法,将所要创建的具体对 象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。

 Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。

Abstract Factory 抽象工厂

**动机(Motivation)**💡:

在软件系统中,经常面临着**“一系列相互依赖的对象”**的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。

**问题思考(Consider)**🤔:

如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?

EmployeeDAO1.cpp

#include<vector>
#include<string>
using std::string;
using std::vector;

class EmployeeDO{

};

class SqlConnection{
public:
    string ConnectionString;
};

class SqlCommand{
public:
    string CommandText;
    SqlConnection* connection;
    
    void SetConnection(SqlConnection* p){
        this->connection = p;
    }
    
    SqlDataReader* ExecuteReader(){
        // ...
        return nullptr;
    }
};

class SqlDataReader{
public:
    bool Read(){
        // ...
        return true;
    }
};

class EmployeeDAO{
public:
    vector<EmployeeDO> GetEmployees(){
        SqlConnection* connection = new SqlConnection();
        connection->ConnectionString = "...";

        SqlCommand* command = new SqlCommand();
        command->CommandText="...";
        command->SetConnection(connection);

        SqlDataReader* reader = command->ExecuteReader();
        while (reader->Read()){
            // ...
        }
    }
};

EmployeeDAO2.cpp

**缺点:这三个必须是同系列的,有关联性
无法实现不同工厂生产出来的是不同组的东西,无法搭配到一起
即只能实现sql系列和oracle系列,无法实现sql和oracle的混合搭配系列


//数据库访问有关的基类
//支持图像数据库(IDB)
class IDBConnection{
    
};
class IDBConnectionFactory{
public:
    virtual IDBConnection* CreateDBConnection()=0;
};


class IDBCommand{
    
};
class IDBCommandFactory{
public:
    virtual IDBCommand* CreateDBCommand()=0;
};


class IDataReader{
    
};
class IDataReaderFactory{
public:
    virtual IDataReader* CreateDataReader()=0;
};



//支持SQL Server
class SqlConnection: public IDBConnection{
    
};
class SqlConnectionFactory:public IDBConnectionFactory{
    
};


class SqlCommand: public IDBCommand{
    
};
class SqlCommandFactory:public IDBCommandFactory{
    
};


class SqlDataReader: public IDataReader{
    
};
class SqlDataReaderFactory:public IDataReaderFactory{
    
};


//支持Oracle
class OracleConnection: public IDBConnection{
    
};
class OracleConnectionFactory :public IDBConnectionFactory {

};


class OracleCommand: public IDBCommand{
    
};
class OracleCommandFactory :public IDBCommandFactory {

};


class OracleDataReader: public IDataReader{
    
};
class OracleDataReaderFactory :public IDataReaderFactory {

};

class EmployeeDAO{
    /*
    	缺点:这三个必须是同系列的,有关联性
    	无法实现不同工厂生产出来的是不同组的东西,无法搭配到一起
    	即只能实现sql系列和oracle系列,无法实现sql和oracle的混合搭配系列
    */
    IDBConnectionFactory* dbConnectionFactory;
    IDBCommandFactory* dbCommandFactory;
    IDataReaderFactory* dataReaderFactory;
    
public:
    vector<EmployeeDO> GetEmployees(){
        IDBConnection* connection =
            dbConnectionFactory->CreateDBConnection();
        connection->ConnectionString("...");

        IDBCommand* command =
            dbCommandFactory->CreateDBCommand();
        command->CommandText("...");
        command->SetConnection(connection); //关联性

        IDBDataReader* reader = command->ExecuteReader(); //关联性
        while (reader->Read()){

        }

    }
};

EmployeeDAO3.cpp

将三个工厂合并为一个

在这里插入图片描述


//数据库访问有关的基类
//支持图像数据库(IDB)
class IDBConnection{
    
};

class IDBCommand{
    
};

class IDataReader{
    
};


class IDBFactory{
public:
    virtual IDBConnection* CreateDBConnection()=0;
    virtual IDBCommand* CreateDBCommand()=0;
    virtual IDataReader* CreateDataReader()=0;
    
};


//支持SQL Server
class SqlConnection: public IDBConnection{
    
};
class SqlCommand: public IDBCommand{
    
};
class SqlDataReader: public IDataReader{
    
};


class SqlDBFactory:public IDBFactory{
public:
    virtual IDBConnection* CreateDBConnection()=0;
    virtual IDBCommand* CreateDBCommand()=0;
    virtual IDataReader* CreateDataReader()=0;
 
};

//支持Oracle
class OracleConnection: public IDBConnection{
    
};

class OracleCommand: public IDBCommand{
    
};

class OracleDataReader: public IDataReader{
    
};


class EmployeeDAO{
    IDBFactory* dbFactory;
    
public:
    vector<EmployeeDO> GetEmployees(){
        IDBConnection* connection =
            dbFactory->CreateDBConnection();
        connection->ConnectionString("...");

        IDBCommand* command =
            dbFactory->CreateDBCommand();
        command->CommandText("...");
        command->SetConnection(connection); //关联性

        IDBDataReader* reader = command->ExecuteReader(); //关联性
        while (reader->Read()){

        }

    }
};

AbstractFactory1.cpp

#include<iostream>
using namespace std;

//船体
class ShipBody {
public:
	virtual string getShipBody() = 0;
	virtual ~ShipBody() {};
};

//木材船体
class WoodBody : public ShipBody {
public:
	string getShipBody() override {
		return string("用<木材>制作轮船船体...");
	}
};

//钢铁船体
class IronBody : public ShipBody {
public:
	string getShipBody() override {
		return string("用<钢铁>制作轮船船体...");
	}
};

//金属船体
class MetalBody : public ShipBody {
public:
	string getShipBody() override {
		return string("用<合金>制作轮船船体...");
	}
};

//动力
class Engine {
public:
	virtual string getEngine() = 0;
	virtual ~Engine() {}
};

class Human :public Engine {
public:
	string getEngine() override{
		return string("使用<人力驱动>");
	}
};

class Diesel :public Engine {
public:
	string getEngine() override {
		return string("使用<内燃机驱动>");
	}
};

class Nuclear :public Engine {
public:
	string getEngine() override {
		return string("使用<核能驱动>");
	}
};

//武器
class Weapon {
public:
	virtual string getWeapon() = 0;
	virtual ~Weapon() {};
};

class Gun :public Weapon {
public:
	string getWeapon() override {
		return string("配备的武器是<枪>");
	}
};

class Cannon :public Weapon {
public:
	string getWeapon() override {
		return string("配备的武器是<自动机关炮>");
	}
};

class Laser : public Weapon
{
public:
	string getWeapon() override
	{
		return string("配备的武器是<激光>");
	}
};

//轮船类
class Ship {
public:
	Ship(ShipBody* body, Weapon* weapon, Engine* engine) :
		m_body(body), m_weapon(weapon), m_engine(engine) {}
	string getProperty() {
		string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();
		return info;
	}
	~Ship(){
		delete m_body;
		delete m_weapon;
		delete m_engine;
	}

private:
	ShipBody* m_body = nullptr;
	Weapon* m_weapon = nullptr;
	Engine* m_engine = nullptr;
};

//工厂类
class AbstractFactory {
public:
	virtual Ship* createShip() = 0;
	virtual ~AbstractFactory() {}
};

class BasicFactory :public AbstractFactory {
public:
	Ship* createShip() override {
		Ship* ship = new Ship(new WoodBody, new Gun, new Human);
		cout << "<基础型>战船生产完毕, 可以下水啦..." << endl;
		return ship;
	}
};

class StandardFactory : public AbstractFactory {
public:
	Ship* createShip() override {
		Ship* ship = new Ship(new IronBody, new Cannon, new Diesel);
		cout << "<标准型>战船生产完毕, 可以下水啦..." << endl;
		return ship;
	}
};

class UltimateFactory : public AbstractFactory {
public:
	Ship* createShip() override {
		Ship* ship = new Ship(new MetalBody, new Laser, new Nuclear);
		cout << "<旗舰型>战船生产完毕, 可以下水啦..." << endl;
		return ship;
	}
};

int main() {
	AbstractFactory* basicFactory = new BasicFactory();
	Ship* basicShip = basicFactory->createShip();
	cout << basicShip->getProperty() << endl;
	delete basicShip;
	delete basicFactory;

	AbstractFactory* standardFactory = new StandardFactory();
	Ship* standardShip = standardFactory->createShip();
	cout << standardShip->getProperty() << endl;
	delete standardShip;
	delete standardFactory;

	AbstractFactory* ultimateFactory = new UltimateFactory();
	Ship* ultimateShip = ultimateFactory->createShip();
	cout << ultimateShip->getProperty() << endl;
	delete ultimateShip;
	delete ultimateFactory;

	return 0;
}

在这里插入图片描述

AbstractFactory2.cpp

#include <iostream>
using namespace std;

class AbstractProductA
{
public:
    virtual ~AbstractProductA() {}
    virtual const char* getName() = 0;
};
class ProductA1 : public AbstractProductA
{
public:
    ~ProductA1() {}
    const char* getName()
    {
        return "A1";
    }
};

class ProductA2 : public AbstractProductA
{
public:
    ~ProductA2() {}
    const char* getName()
    {
        return "A2";
    }
};

class AbstractProductB
{
public:
    virtual ~AbstractProductB() {}
    virtual const char* getName() = 0;
};

class ProductB1 : public AbstractProductB
{
public:
    ~ProductB1() {}
    const char* getName()
    {
        return "B1";
    }
};

class ProductB2 : public AbstractProductB
{
public:
    ~ProductB2() {}
    const char* getName()
    {
        return "B2";
    }
};

class AbstractFactory
{
 public:
    virtual ~AbstractFactory() {}
  
    virtual AbstractProductA *CreateProductA() = 0;
    virtual AbstractProductB *CreateProductB() = 0;
};

class ConcreteFactory1 : public AbstractFactory
{
public:
    ~ConcreteFactory1() {}

    AbstractProductA* CreateProductA()
    {
        return new ProductA1();
    }
    AbstractProductB* CreateProductB()
    {
        return new ProductB1();
    }
};

class ConcreteFactory2 : public AbstractFactory
{
public:
    ~ConcreteFactory2() {}

    AbstractProductA *CreateProductA()
    {
        return new ProductA2();
    }
    AbstractProductB *CreateProductB()
    {
        return new ProductB2();
    }
};


int main()
{
    ConcreteFactory1 *factory1 = new ConcreteFactory1();
    ConcreteFactory2 *factory2 = new ConcreteFactory2();

    cout << "-------------ConcreteFactory1(CreateProductA,CreateProductB)-------------" << endl;
    AbstractProductA *p11 = factory1->CreateProductA();
    std::cout << "Product: " << p11->getName() << std::endl;
    AbstractProductB* p12 = factory1->CreateProductB();
    std::cout << "Product: " << p12->getName() << std::endl;
  
    cout << "-------------ConcreteFactory2(CreateProductA,CreateProductB)-------------" << endl;
    AbstractProductA *p21 = factory2->CreateProductA();
    std::cout << "Product: " << p21->getName() << std::endl;
    AbstractProductB* p22 = factory2->CreateProductB();
    std::cout << "Product: " << p22->getName() << std::endl;
  
    delete p11;
    delete p12;
    delete p21;
    delete p22;
  
    delete factory1;
    delete factory2;
  
    return 0;
}

在这里插入图片描述

模式定义

提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。

——《设计模式》GoF

结构(Structure)

在这里插入图片描述

要点总结

 如果没有应对**“多系列对象构建”**的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。

 “系列对象”指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖

 Abstract Factory模式主要在于应对“新系列”的需求变动其缺点在于难以应对“新对象”的需求变动

Prototype原型模式

**动机(Motivation)**💡:

 在软件系统中,经常面临着**“某些结构复杂的对象”**的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。

**问题思考(Consider)**🤔:

 如何应对这种变化? 如何向**“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”**不随着需求改变而改变?

C++执行代码:

Prototype.cpp

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

};

ConCretePrototype.cpp

#include"Prototype.cpp"

//具体类
class BinarySplitter : public ISplitter{
public:
    virtual void split(){}
    virtual ISplitter* clone(){
        return new BinarySplitter(*this);
    }
};

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

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

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

Client.cpp (原型对象只供克隆,不能使用)

#include"Prototype.cpp"
class Form{

};

class MainForm : public Form
{
    ISplitter*  prototype;//原型对象

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

		ISplitter * splitter=
            prototype->clone(); //克隆原型
        
        splitter->split();
	}
};

网上代码(来自这个博主):https://github.com/chouxianyu/design-patterns-cpp

Prototype.cpp

#include <iostream>
#include <string>

class Prototype
{
public:
    virtual ~Prototype() {}
  
    virtual Prototype* clone() = 0;
    virtual std::string type() = 0;
};

class ConcretePrototypeA : public Prototype
{
public:
    ~ConcretePrototypeA() {}
  
    Prototype* clone()
    {
        return new ConcretePrototypeA();
    }
    std::string type()
    {
        return "type A";
    }
};

class ConcretePrototypeB : public Prototype
{
public:
    ~ConcretePrototypeB() {}
  
    Prototype* clone()
    {
        return new ConcretePrototypeB();
    }
    std::string type()
    {
        return "type B";
    }
};

class Client
{
public:
    static void init()
    {
        types[ 0 ] = new ConcretePrototypeA();
        types[ 1 ] = new ConcretePrototypeB();
    }
  
    static void remove()
    {
        delete types[ 0 ];
        delete types[ 1 ];
    }
  
    static Prototype* make( const int index )
    {
        if ( index >= n_types )
        {
            return nullptr;
        }    
        return types[ index ]->clone();
    }

    private:
    static Prototype* types[ 2 ];
    static int n_types;
};

Prototype* Client::types[ 2 ];
int Client::n_types = 2;

int main()
{
    Client::init();
  
    Prototype *prototype1 = Client::make( 0 );
    std::cout << "Prototype: " << prototype1->type() << std::endl;
    delete prototype1;
  
    Prototype *prototype2 = Client::make( 1 );
    std::cout << "Prototype: " << prototype2->type() << std::endl;
    delete prototype2;
  
    Client::remove();
  
    return 0;
}

在这里插入图片描述

RobotPrototype.cpp

#include <iostream>
using namespace std;

class Robot {
public:
    virtual Robot* clone() = 0;
    virtual string selfIntroduction() = 0;
    virtual ~Robot() {}
};

class Robot10086 : public Robot {
public:
    Robot* clone() override{
        return new Robot10086(*this);
    }
    string selfIntroduction()override {
        return string("我是机器人10086,可以为您提供话费咨询服务!!!");
    }
};

class Robot10087 : public Robot {
public:
    Robot* clone() override{
        return new Robot10087(*this);
    }
    string selfIntroduction() override {
        return string("我是机器人10087,可以为您提供流量查询服务!!!");
    }
};

int main()
{
    Robot* obj = new Robot10086;
    Robot* robot = obj->clone();
    cout << robot->selfIntroduction() << endl;
    delete robot;
    delete obj;

    Robot* obj1 = new Robot10087;
    Robot* robot1 = obj1->clone();
    cout << robot1->selfIntroduction() << endl;
    delete robot1;
    delete obj1;
    return 0;
}

在这里插入图片描述

模式定义

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
——《设计模式》 GoF

结构(Structure)

在这里插入图片描述

要点总结

 Prototype模式同样用于隔离类对象的使用者和具体类型 (易变类)之间的耦合关系,它同样要求这些**“易变类”拥有“稳定的接口”**。

 Prototype模式对于**“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”**的新对象一-所需工作仅仅是注册一个新类的对象 (即原型)然后在任何需要的地方Clone。

 Prototype模式中的Clone方法可以利用某些框架中的序列化来实现深拷贝

Builder 构建器

**动机(Motivation)**💡:

在软件系统中,有时候面临着**“一个复杂对象”**的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

**问题思考(Consider)**🤔:

如何应对这种变化?如何提供一种**“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”**不随着需求改变而改变?

C++执行代码:

builder.cpp

class House{
    //....
};

class HouseBuilder {
public:
    House* pHouse;

    House* GetResult(){
        return pHouse;
    }
    virtual ~HouseBuilder(){}
	virtual void BuildPart1()=0;
    virtual void BuildPart2()=0;
    virtual bool BuildPart3()=0;
    virtual void BuildPart4()=0;
    virtual void BuildPart5()=0;
	
};

class StoneHouse: public House{
    
};

class StoneHouseBuilder: public HouseBuilder{
public:
    
    virtual void BuildPart1(){
        //pHouse->Part1 = ...;
    }
    virtual void BuildPart2(){
        
    }
    virtual bool BuildPart3(){
        
    }
    virtual void BuildPart4(){
        
    }
    virtual void BuildPart5(){
        
    }
    
};


class HouseDirector{
    
public:
    HouseBuilder* pHouseBuilder;
    
    HouseDirector(HouseBuilder* pHouseBuilder){
        this->pHouseBuilder=pHouseBuilder;
    }
    
    House* Construct(){
        
        pHouseBuilder->BuildPart1();
        
        for (int i = 0; i < 4; i++){
            pHouseBuilder->BuildPart2();
        }
        
        bool flag=pHouseBuilder->BuildPart3();
        
        if(flag){
            pHouseBuilder->BuildPart4();
        }
        
        pHouseBuilder->BuildPart5();
        
        return pHouseBuilder->GetResult();
    }
};

Builder.cpp

#include <iostream>
#include <string>

class Product
{
public:
    void makeA( const std::string &part )
    {
        partA = part;
    }
    void makeB( const std::string &part )
    {
        partB = part;
    }
    void makeC( const std::string &part )
    {
        partC = part;
    }
    std::string get()
    {
        return (partA + " " + partB + " " + partC);
    }
  
private:
    std::string partA;
    std::string partB;
    std::string partC;
};

class Builder
{
public:
    virtual ~Builder() {}
  
    Product get()
    {
        return product;
    }
  
    virtual void buildPartA() = 0;
    virtual void buildPartB() = 0;
    virtual void buildPartC() = 0;

protected:
    Product product;
};

class ConcreteBuilderX : public Builder
{
public:
    void buildPartA()
    {
        product.makeA( "A-X" );
    }
    void buildPartB()
    {
        product.makeB( "B-X" );
    }
    void buildPartC()
    {
        product.makeC( "C-X" );
    }
};

class ConcreteBuilderY : public Builder
{
public:
    void buildPartA()
    {
        product.makeA( "A-Y" );
    }
    void buildPartB()
    {
        product.makeB( "B-Y" );
    }
    void buildPartC()
    {
        product.makeC( "C-Y" );
    }
};

class Director {
public:
    Director() : builder() {}
  
    ~Director()
    {
        if ( builder )
        {
            delete builder;
        }
    }
  
    void set( Builder *b )
    {
        if ( builder )
        {
            delete builder;
        }
        builder = b;
    }
  
    Product get()
    {
        return builder->get();
    }
  
    void construct()
    {
        builder->buildPartA();
        builder->buildPartB();
        builder->buildPartC();
    }

private:
    Builder *builder;
};


int main()
{
    Director director;
    director.set( new ConcreteBuilderX );
    director.construct();
  
    Product product1 = director.get();
    std::cout << "1st product parts: " << product1.get() << std::endl;
  
    director.set( new ConcreteBuilderY );
    director.construct();
  
    Product product2 = director.get();
    std::cout << "2nd product parts: " << product2.get() << std::endl;
  
    return 0;
}

在这里插入图片描述

模式定义

将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。

——《设计模式》GoF

结构(Structure)

在这里插入图片描述

要点总结

 Builder 模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

 变化点在哪里,封装哪里—— Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。

 在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#) 。

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

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

相关文章

【Java】Java核心要点总结 68

文章目录 1. 为什么重写 equals() 时候必须重写 hashCode()2. 字符串常量池3. 字符串中的 intern() 方法4. try-catch-finally5. finally 中的代码不一定会执行 1. 为什么重写 equals() 时候必须重写 hashCode() 因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equ…

三、动画 -变形transform

目录&#xff1a; 1.变形transform定义 2.具体描述 3.用途 4.练习 一、变形transform定义 变形就是指通过CSS来改变元素的形状或位置 变形不会影响到页面的布局transform 用来设置元素的变形效果设置具体的值用translate()函数 二、具体描述 - 平移&#xff1a;translateX() 沿…

2023 3de实时仿真环境下资源不可见或没有了(只有floor)

F3退出实时仿真环境&#xff0c;双击结构树父节点 之后再进入实时仿真&#xff0c;3d仿真&#xff0c;再打开资源就可以看到了。

【雕爷学编程】Arduino动手做(117)---P10V706LED屏模组

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

【Atlas 200DK A2体验】Atlas 200DK A2初体验记录

开箱照 烧录镜像 Windows版制卡工具下载地址&#xff1a; https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/Atlas%20200I%20DK%20A2/DevKit/tools/latest/Ascend-devkit-imager_latest_win-x86_64.exe 准备一张MicroSD卡&#xff0c;个人建议容量至少在64GB以上 一键制…

6 月份有哪些 GitHub 项目火了?

本期推荐开源项目目录&#xff1a; 1. 谁在招人&#xff1f; 2. ChatGPT-Midjourney 3. 让 AI 给你写代码 4. 免费的 OpenAI GPT-4 的 API 5. 金融领域的大模型 6. 文本生成音乐模型 01 谁在招人&#xff1f; 阮一峰在 GitHub 上维护了一个《科技爱好者周刊》&#xff0c;每周五…

开源的可视化爬虫易采集EasySpider:如何无代码可视化的爬取需要登录才能爬的网站

一个可视化爬虫软件&#xff0c;可以使用图形化界面&#xff0c;无代码可视化的设计和执行爬虫任务。只需要在网页上选择自己想要爬的内容并根据提示框操作即可完成爬虫设计和执行。同时软件还可以单独以命令行的方式进行执行&#xff0c;从而可以很方便的嵌入到其他系统中。 …

AI导师、AI提示工程师 # Earth实现任意角色设定

‍‍ 如何通过学习优秀的开源项目&#xff0c; 设定一个任意角色 opus 嗨&#xff0c;Shadow&#xff0c;我想学习如何给ChatGPT设定一个角色&#xff0c;可以教我吗&#xff1f; 当然可以&#xff0c;我们可以通过学习优秀的开源项目来了解实现细节。 shadow 其中&#xff0c;…

SQLmap使用教程图文教程(超详细)

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 SQLmap 一、目标1、指定url2、指定文件&#xff08…

ICLR Oral总分世界第五(10,8,8):可学习的行为控制,超越DeepMind和OpenAI突破Atari人类世界纪录...

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 作者介绍 范嘉骏 清华大学计算机技术专业二年级研究生&#xff0c;主要研究深度强化学习 报告题目 可学习的行为控制&#xff0c;超越DeepMind和OpenAI突破Atari人类世界纪录 内容简介 探索问题一直是深度强化学…

【kafka】kafka基础架构

文章目录 1、kafka简介2、kafka的特性3、kafka的应用场景4、kafka架构&#xff08;重点&#xff09;4.1、broker4.2、topic4.3、partition4.4、offset4.5、producer4.6、consumer4.7、consumer group4.8、leader4.9、follower4.10、rebalance 5、对kafka架构的几点解释6、几种M…

突破软件测试的瓶颈

软件测试两三年&#xff0c;编程能力半生不熟&#xff0c;三流学校出身&#xff0c;E很差&#xff0c;工作主要还是写各种测试文档和手工测试&#xff1b;相信不少测试人员都和这情况相似&#xff1b;下面就这几个方面谈一下自己的看法。 关于编程的能力 之前有同学问我测试要学…

青翼自研-模块化互联产品 • 模拟采集FMC子卡产品资料

FMC123是一款基于FMC标准规范&#xff0c;实现2路14-bit、3GSPS ADC采集功能、2路16-bit 12.6GSPS回放子卡模块。该模块遵循VITA57.1标准&#xff0c;可直接与FPGA载卡配合使用&#xff0c;板卡ADC器件采用ADI公司的AD9208芯片&#xff0c;&#xff0c;与ADI公司的AD9689可以实…

C国演义 [第五章]

第五章 子集题目理解步骤树形结构递归函数递归结束的条件单层逻辑 代码 子集II题目理解步骤树形结构递归函数递归结束的条件单层逻辑 代码 子集 力扣链接 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。…

MySQL索引、事务、与存储引擎

MySQL索引、事务、与存储引擎 一、索引 1.概念 索引是一个排序的列表&#xff0c;包含索引字段的值和其相对应的行数据所在的物理地址2.作用 优点 加快表的查询速度 可以对字段排序缺点 额外占用磁盘空间 更新包含索引的表效率会更慢3.索引工作模式 没有索引的情况下&am…

利用C语言创建图书管理系统

不仅仅是图书信息管理系统 基于双链表&#xff0c;采用面向对象编程方法制作的图书管理系统 ❞ 效果演示 root用户&#xff1a;账号&#xff1a;0&#xff0c;密码&#xff1a;0 普通用户&#xff1a;账号&#xff1a;1001&#xff0c;密码&#xff1a;666666 图书信息 没有完全…

Spring MVC各种参数进行封装

目录 一、简单数据类型 1.1 控制器方法 1.2 测试结果 二、对象类型 2.1 单个对象 2.1.1 控制器方法 2.1.2 测试结果 2.2 关联对象 2.2.1 控制器方法 2.2.2 测试结果 三、集合类型 3.1 简单数据类型集合 3.1.1 控制方法 3.1.2 测试结果 3.2 对象数据类型集合 3.…

KMP算法实现strStr(c++代码实现)

1 KMP算法简介 KMP算法是一个解决字符串匹配问题的算法&#xff0c;由D.E.Knuth&#xff0c;J.H.Morris和V.R.Pratt提出。当给你一个主串str和一个子串substr&#xff0c;如何确定substr在主串中出现的位置&#xff1f;如果没有学习KMP算法&#xff0c;我们可能会写出这样的代…

测试(三)——黑盒测试

一、测试用例的基本要素 测试环境、操作步骤、测试数据、预期结果 测试用例的好处&#xff1a; 1.能提高测试效率、节省测试时间 2.测试用例是自动化测试用例的前提 二、测试用例的设计方法 2.1基于需求进行测试用例设计 2.2具体的设计方法 2.2.1等价类 有效等价类&#x…

c++学生信息管理系统

前言 c课程作业–学生信息管理系统 在 原博客C通讯录管理系统 https://www.csdn.net/tags/OtDagg2sODU2Ni1ibG9n.html 的基础上进行了一点修改。 学生信息管理系统 基本功能要求&#xff1a; 能使用文件的打开&#xff0c;关闭&#xff0c;读写等操作&#xff0c;实现 1.连…