设计模式解释与例子(C++)

设计Modern

这里的介绍一下设计模式的几种在(我的)工作种常用的模型,以及其代码和伪代码。此处主要作为一个知识积累库。如需详尽的解释还需百度。

观察者模式

用户往一个地方注册一个观察, 如果当观察者有探测到用户观察的消息,就推送给回给用户。观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

class Observer
{
public:
    Observer(){}
    virtual ~Observer(){}
    virtual void update(Subject *subject) = 0;
    virtual void update(string content) = 0;
};


class  Subject
{
public:
    Subject() {}
    virtual ~ Subject() {}
    virtual string getContent() = 0;
    virtual string getAbstractContent() = 0;
    virtual void setContent(string content) = 0;
    // 订阅主题
    void attach(Observer *observer) {
        observers.push_back(observer);
    }
    // 取消订阅
    void detach(Observer *observer) {
        observers.remove(observer);
    }

    // 通知所有的订阅者
    virtual void notifyObservers() {
        for(Observer *reader: observers) {
            // 拉模型  (也是有推送的性质,只是粒度小一些)
            reader->update(this);
        }
    }
    // 通知所有的订阅者
    virtual void notifyObservers(string content) {
        for(Observer *reader: observers) {
            // 推模型
            reader->update(content);
        }
    }
private:
    list<Observer *> observers;    // 保存注册的观察者
};

class Reader : public Observer
{
public:
    Reader() {}
    virtual ~Reader() {}
    virtual void update(Subject *subject) {
        // 调用对应的方法去拉取内容 subject->getContent()
        cout << m_name << "收到报纸和阅读它, 具体内容" << subject->getContent() << endl;
    }
    virtual void update(string content) {
        // 推模型
        cout << m_name << "收到报纸和阅读它, 具体内容" << content << endl;
    }
    string getName() {
        return m_name;
    }
    void setName(string name) {
        m_name = name;
    }
private:
    string m_name;
};


class NewsPaper: public Subject
{
public:
    NewsPaper() {}
    virtual ~NewsPaper() {}

    void setContent(string content) {
        m_content = content;
        notifyObservers();
    }
    virtual string getContent() {
        return m_content;
    }
    virtual string getAbstractContent() {
        return  "摘要:";
    }
private:
    string m_content;
};

责任链模式

这个模式和上面的模式也是差不多的,只不过多了个等级的划分而已。责任链是一种行为设计模式, 允许你将请求沿着处理者链进行发送, 直至其中一个处理者对其进行处理。

该模式允许多个对象来对请求进行处理, 而无需让发送者类与具体接收者类相耦合。 链可在运行时由遵循标准处理者接口的任意处理者动态生成。

class WaterQualitySubject;

// 观察者的接口
/**
 * 水质观察者接口定义
 */
class WatcherObserver
{
public:
    WatcherObserver(){}
    virtual ~WatcherObserver(){}
    /**
     * 被通知的方法
     * @param subject 传入被观察的目标对象
     */
    virtual void update(WaterQualitySubject *subject) = 0;

    // 和普通观察者模式, 增加了角色
    /**
     * 设置观察人员的职务
     * @param job 观察人员的职务
     */
    virtual void setJob(string job) = 0;

    /**
     * 获取观察人员的职务
     * @return 观察人员的职务
     */
    virtual string getJob() = 0;
};

/**
* 定义水质监测的目标对象
*/
class WaterQualitySubject {
public:
    WaterQualitySubject(){}
    virtual ~WaterQualitySubject(){}
    /**
    * 注册观察者对象
     * @param observer 观察者对象
     */
    void attach(WatcherObserver *observer) {
        observers.push_back(observer);
    }

    /**
     * 删除观察者对象
     * @param observer 观察者对象
     */
    void detach(WatcherObserver *observer) {
        observers.remove(observer);
    }

    /**
     * 通知相应的观察者对象
     */
    virtual void notifyWatchers() = 0;

    /**
     * 获取水质污染的级别
     * @return 水质污染的级别
     */
    virtual int getPolluteLevel() = 0;
protected:
    /**
     * 用来保存注册的观察者对象
     */
    list<WatcherObserver *> observers;
};

/**
 * 具体的观察者实现
 */
class Watcher: public WatcherObserver
{
public:
    Watcher(){}
    virtual ~Watcher(){}
    string getJob() {
        return m_job;
    }

    void setJob(string job) {
        m_job = job;
    }

    virtual void update(WaterQualitySubject *subject) {
        //这里采用的是拉的方式
        cout << m_job << " 获取到通知,当前污染级别为:" << subject->getPolluteLevel() <<endl;
    }
private:
    /**
     * 职务
     */
    string m_job;
};



/**
 * 具体的水质监测对象
 */
class WaterQuality: public WaterQualitySubject
{
public:
    WaterQuality(){}
    virtual ~WaterQuality(){}
    /**
     * 获取水质污染的级别
     * @return 水质污染的级别
     */
    int getPolluteLevel() {
        return m_polluteLevel;
    }

    /**
     * 当监测水质情况后,设置水质污染的级别
     * @param polluteLevel 水质污染的级别
     */
    virtual void setPolluteLevel(int polluteLevel) {
        m_polluteLevel = polluteLevel;
        //通知相应的观察者
        notifyWatchers();
    }

    /**
     * 通知相应的观察者对象
     */

    virtual void notifyWatchers() {
        //循环所有注册的观察者
        for(WatcherObserver *watcher : observers){
            //开始根据污染级别判断是否需要通知,由这里总控
            if(m_polluteLevel >= 0){
                //通知监测员做记录
                if(watcher->getJob().compare("监测人员") == 0){
                    watcher->update(this);
                }
            }

            if(m_polluteLevel >= 1){
                //通知预警人员
                if(watcher->getJob().compare("预警人员") == 0){
                    watcher->update(this);
                }

            }

            if(m_polluteLevel >= 2){
                //通知监测部门领导
                if(watcher->getJob().compare("监测部门领导") == 0){
                    watcher->update(this);
                }
            }
        }
    }
private:
    /**
     * 污染的级别,0表示正常,1表示轻度污染,2表示中度污染,3表示高度污染
     */
    int m_polluteLevel = 0;
};


int main()
{
    //创建水质主题对象
    WaterQuality *subject = new WaterQuality();
    //创建几个观察者, 观察者分了不同角色
    WatcherObserver *watcher1 = new Watcher();
    watcher1->setJob("监测人员");
    WatcherObserver *watcher2 = new Watcher();
    watcher2->setJob("预警人员");
    WatcherObserver *watcher3 = new Watcher();
    watcher3->setJob("监测部门领导");

    //注册观察者
    subject->attach(watcher1);
    subject->attach(watcher2);
    subject->attach(watcher3);

    //填写水质报告
    cout << "当水质为正常的时候------------------〉" << endl;
    subject->setPolluteLevel(0);

    cout << "\n当水质为轻度污染的时候---------------〉"<< endl;
    subject->setPolluteLevel(1);

    cout << "\n当水质为中度污染的时候---------------〉"<< endl;
    subject->setPolluteLevel(2);

    // 释放观察者
    subject->detach(watcher1);
    subject->detach(watcher2);
    subject->detach(watcher3);

    delete watcher1;
    delete watcher2;
    delete watcher3;

    delete subject;

    return 0;
}

抽象工厂模式

抽象工厂本质上是为不同组件或其相互依赖的对象提供创建接口,而无需指定具体的类。能够有效的确保这些相互依赖对象的一致性(客户根据实例化不同的工厂类,只能获取与该工厂中一系列相关的产品)。

工厂类一般为单实例,客户仅需初始化不同的工厂实例就可以获得不同的对象类型。

class AbstractFactory
{
public:
	virtual Object_A* createA() =0
	{
		return new Object_A;
	}
	virtual Object_N* createN() =0
	{
		return new Object_N;
	}
};

class AbstractFactory_Huawei:public AbstractFactory
{
	virtual Object_A* createA(){return new Object_AA1;};
	virtual Object_N* createN(){return new Object_NN1;};
};

class AbstractFactory_Xiaomi:public AbstractFactory
{
	virtual Object_A* createA(){return new Object_AA2;};
	virtual Object_N* createN(){return new Object_NN2;};
};

工厂方法

这个方法本质上可以说就是创建一个对象的两个通用属性,然后具体然后需要其子类去现实它具体的功能。

例如我们经常使用的导出用户数据,我们有好多种方法导出,一种是导入到数据库,一种是导入到本地XML,一种是写入日志,导出数据就是一个通用属性,而不同的导出的方式就是其具体的功能。

#include <iostream>

using namespace std;

class ExportFileProduct
{
public:
    ExportFileProduct() {}
    virtual ~ExportFileProduct() {}

    virtual bool Export(string data) = 0;
};

// 保存成文件
class ExportTextProduct: public ExportFileProduct
{
public:
    ExportTextProduct() {}
    virtual ~ExportTextProduct() { }
    virtual bool Export(string data) {
        cout << "导出数据:[" << data << "]保存成文本的方式" << endl;
        return true;
    }

};

class ExportDBProduct: public ExportFileProduct
{
public:
    ExportDBProduct() {}
    virtual ~ExportDBProduct() { }
    virtual bool Export(string data) {
        cout << "导出数据:[" << data << "]保存数据库的方式" << endl;
        return true;
    }

};

class ExportFactory
{
public:
    ExportFactory() {}
    virtual ~ExportFactory() {}
    /**
     * @brief Export
     * @param type 导出的类型
     * @param data 具体的数据
     * @return
     */
    virtual bool Export(int type, string data) {
        ExportFileProduct *product = nullptr;
        product = factoryMethod(type);

        bool ret = false;
        if(product) {
            ret = product->Export(data);
            delete product;
        } else {
            cout << "没有对应的导出方式";
        }
        return ret;
    }
protected:
    virtual ExportFileProduct *factoryMethod(int type) {
        ExportFileProduct *product = nullptr;
        if(1 == type) {
            product = new ExportTextProduct();
        } else if(2 == type) {
            product = new ExportDBProduct();
        }
        return product;
    }
};

// 加一种新的导出方式:
// (1)修改原来的工厂方法
// (2)继承工厂方法去拓展
class ExportXMLProduct: public ExportFileProduct
{
public:
    ExportXMLProduct() {}
    virtual ~ExportXMLProduct() { }
    virtual bool Export(string data) {
        cout << "导出数据:[" << data << "]保存XML的方式" << endl;
        return true;
    }

};

class ExportPortobufferProduct: public ExportFileProduct
{
public:
    ExportPortobufferProduct() {}
    virtual ~ExportPortobufferProduct() { }
    virtual bool Export(string data) {
        cout << "导出数据:[" << data << "]保存Portobuffer的方式" << endl;
        return true;
    }

};

class ExportFactory2: public ExportFactory
{
public:
    ExportFactory2() {}
    virtual ~ExportFactory2() {}
protected:
    virtual ExportFileProduct *factoryMethod(int type) {
        ExportFileProduct *product = nullptr;
        if(3 == type) {
            product = new ExportXMLProduct();
        } else if(4 == type) {
            product = new ExportPortobufferProduct();
        } else {
            product = ExportFactory::factoryMethod(type);
        }
        return product;
    }
};

int main()
{
    cout << "ExportFactory" << endl;
    ExportFactory *factory = new ExportFactory();

    factory->Export(1, "上课人数");
    factory->Export(2, "上课人数");
    factory->Export(3, "上课人数");

    cout << "\nExportFactory2" << endl;
    ExportFactory *factory2 = new ExportFactory2();

    factory2->Export(1, "上课人数");
    factory2->Export(2, "上课人数");
    factory2->Export(3, "上课人数");
    factory2->Export(4, "上课人数");

    delete factory;
    delete factory2;
    return 0;
}

生成器(Builder)

生成器使我们可以将数据的构建和表现形式分开来,允许使用相同的创建代码生成不同类型和形式的对象。

/**
 * It makes sense to use the Builder pattern only when your products are quite
 * complex and require extensive configuration.
 *
 * Unlike in other creational patterns, different concrete builders can produce
 * unrelated products. In other words, results of various builders may not
 * always follow the same interface.
 */

class Product1{
    public:
    std::vector<std::string> parts_;
    void ListParts()const{
        std::cout << "Product parts: ";
        for (size_t i=0;i<parts_.size();i++){
            if(parts_[i]== parts_.back()){
                std::cout << parts_[i];
            }else{
                std::cout << parts_[i] << ", ";
            }
        }
        std::cout << "\n\n"; 
    }
};


/**
 * The Builder interface specifies methods for creating the different parts of
 * the Product objects.
 */
class Builder{
    public:
    virtual ~Builder(){}
    virtual void ProducePartA() const =0;
    virtual void ProducePartB() const =0;
    virtual void ProducePartC() const =0;
};
/**
 * The Concrete Builder classes follow the Builder interface and provide
 * specific implementations of the building steps. Your program may have several
 * variations of Builders, implemented differently.
 */
class ConcreteBuilder1 : public Builder{
    private:

    Product1* product;

    /**
     * A fresh builder instance should contain a blank product object, which is
     * used in further assembly.
     */
    public:

    ConcreteBuilder1(){
        this->Reset();
    }

    ~ConcreteBuilder1(){
        delete product;
    }

    void Reset(){
        this->product= new Product1();
    }
    /**
     * All production steps work with the same product instance.
     */

    void ProducePartA()const override{
        this->product->parts_.push_back("PartA1");
    }

    void ProducePartB()const override{
        this->product->parts_.push_back("PartB1");
    }

    void ProducePartC()const override{
        this->product->parts_.push_back("PartC1");
    }

    /**
     * Concrete Builders are supposed to provide their own methods for
     * retrieving results. That's because various types of builders may create
     * entirely different products that don't follow the same interface.
     * Therefore, such methods cannot be declared in the base Builder interface
     * (at least in a statically typed programming language). Note that PHP is a
     * dynamically typed language and this method CAN be in the base interface.
     * However, we won't declare it there for the sake of clarity.
     *
     * Usually, after returning the end result to the client, a builder instance
     * is expected to be ready to start producing another product. That's why
     * it's a usual practice to call the reset method at the end of the
     * `getProduct` method body. However, this behavior is not mandatory, and
     * you can make your builders wait for an explicit reset call from the
     * client code before disposing of the previous result.
     */

    /**
     * Please be careful here with the memory ownership. Once you call
     * GetProduct the user of this function is responsable to release this
     * memory. Here could be a better option to use smart pointers to avoid
     * memory leaks
     */

    Product1* GetProduct() {
        Product1* result= this->product;
        this->Reset();
        return result;
    }
};

/**
 * The Director is only responsible for executing the building steps in a
 * particular sequence. It is helpful when producing products according to a
 * specific order or configuration. Strictly speaking, the Director class is
 * optional, since the client can control builders directly.
 */
class Director{
    /**
     * @var Builder
     */
    private:
    Builder* builder;
    /**
     * The Director works with any builder instance that the client code passes
     * to it. This way, the client code may alter the final type of the newly
     * assembled product.
     */

    public:

    void set_builder(Builder* builder){
        this->builder=builder;
    }

    /**
     * The Director can construct several product variations using the same
     * building steps.
     */

    void BuildMinimalViableProduct(){
        this->builder->ProducePartA();
    }
    
    void BuildFullFeaturedProduct(){
        this->builder->ProducePartA();
        this->builder->ProducePartB();
        this->builder->ProducePartC();
    }
};
/**
 * The client code creates a builder object, passes it to the director and then
 * initiates the construction process. The end result is retrieved from the
 * builder object.
 */
/**
 * I used raw pointers for simplicity however you may prefer to use smart
 * pointers here
 */
void ClientCode(Director& director)
{
    ConcreteBuilder1* builder = new ConcreteBuilder1();
    director.set_builder(builder);
    std::cout << "Standard basic product:\n"; 
    director.BuildMinimalViableProduct();
    
    Product1* p= builder->GetProduct();
    p->ListParts();
    delete p;

    std::cout << "Standard full featured product:\n"; 
    director.BuildFullFeaturedProduct();

    p= builder->GetProduct();
    p->ListParts();
    delete p;

    // Remember, the Builder pattern can be used without a Director class.
    std::cout << "Custom product:\n";
    builder->ProducePartA();
    builder->ProducePartC();
    p=builder->GetProduct();
    p->ListParts();
    delete p;

    delete builder;
}

int main(){
    Director* director= new Director();
    ClientCode(*director);
    delete director;
    return 0;    
}

单例

一次创建多次使用,这个比较简单就不上代码了。

原型模式

原型是一种创建型设计模式, 使你能够复制对象, 甚至是复杂对象, 而又无需使代码依赖它们所属的类。
所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量。

using std::string;

// Prototype Design Pattern
//
// Intent: Lets you copy existing objects without making your code dependent on
// their classes.

enum Type {
  PROTOTYPE_1 = 0,
  PROTOTYPE_2
};

/**
 * The example class that has cloning ability. We'll see how the values of field
 * with different types will be cloned.
 */

class Prototype {
 protected:
  string prototype_name_;
  float prototype_field_;

 public:
  Prototype() {}
  Prototype(string prototype_name)
      : prototype_name_(prototype_name) {
  }
  virtual ~Prototype() {}
  virtual Prototype *Clone() const = 0;
  virtual void Method(float prototype_field) {
    this->prototype_field_ = prototype_field;
    std::cout << "Call Method from " << prototype_name_ << " with field : " << prototype_field << std::endl;
  }
};

/**
 * ConcretePrototype1 is a Sub-Class of Prototype and implement the Clone Method
 * In this example all data members of Prototype Class are in the Stack. If you
 * have pointers in your properties for ex: String* name_ ,you will need to
 * implement the Copy-Constructor to make sure you have a deep copy from the
 * clone method
 */

class ConcretePrototype1 : public Prototype {
 private:
  float concrete_prototype_field1_;

 public:
  ConcretePrototype1(string prototype_name, float concrete_prototype_field)
      : Prototype(prototype_name), concrete_prototype_field1_(concrete_prototype_field) {
  }

  /**
   * Notice that Clone method return a Pointer to a new ConcretePrototype1
   * replica. so, the client (who call the clone method) has the responsability
   * to free that memory. I you have smart pointer knowledge you may prefer to
   * use unique_pointer here.
   */
  Prototype *Clone() const override {
    return new ConcretePrototype1(*this);
  }
};

class ConcretePrototype2 : public Prototype {
 private:
  float concrete_prototype_field2_;

 public:
  ConcretePrototype2(string prototype_name, float concrete_prototype_field)
      : Prototype(prototype_name), concrete_prototype_field2_(concrete_prototype_field) {
  }
  Prototype *Clone() const override {
    return new ConcretePrototype2(*this);
  }
};

/**
 * In PrototypeFactory you have two concrete prototypes, one for each concrete
 * prototype class, so each time you want to create a bullet , you can use the
 * existing ones and clone those.
 */

class PrototypeFactory {
 private:
  std::unordered_map<Type, Prototype *, std::hash<int>> prototypes_;

 public:
  PrototypeFactory() {
    prototypes_[Type::PROTOTYPE_1] = new ConcretePrototype1("PROTOTYPE_1 ", 50.f);
    prototypes_[Type::PROTOTYPE_2] = new ConcretePrototype2("PROTOTYPE_2 ", 60.f);
  }

  /**
   * Be carefull of free all memory allocated. Again, if you have smart pointers
   * knowelege will be better to use it here.
   */

  ~PrototypeFactory() {
    delete prototypes_[Type::PROTOTYPE_1];
    delete prototypes_[Type::PROTOTYPE_2];
  }

  /**
   * Notice here that you just need to specify the type of the prototype you
   * want and the method will create from the object with this type.
   */
  Prototype *CreatePrototype(Type type) {
    return prototypes_[type]->Clone();
  }
};

void Client(PrototypeFactory &prototype_factory) {
  std::cout << "Let's create a Prototype 1\n";

  Prototype *prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_1);
  prototype->Method(90);
  delete prototype;

  std::cout << "\n";

  std::cout << "Let's create a Prototype 2 \n";

  prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_2);
  prototype->Method(10);

  delete prototype;
}

int main() {
  PrototypeFactory *prototype_factory = new PrototypeFactory();
  Client(*prototype_factory);
  delete prototype_factory;

  return 0;
}

适配器

适配器是一种结构型设计模式, 它能使不兼容的对象能够相互合作。
适配器可担任两个对象间的封装器, 它会接收对于一个对象的调用, 并将其转换为另一个对象可识别的格式和接口。

/**
 * The Target defines the domain-specific interface used by the client code.
 */
class Target {
 public:
  virtual ~Target() = default;

  virtual std::string Request() const {
    return "Target: The default target's behavior.";
  }
};

/**
 * The Adaptee contains some useful behavior, but its interface is incompatible
 * with the existing client code. The Adaptee needs some adaptation before the
 * client code can use it.
 */
class Adaptee {
 public:
  std::string SpecificRequest() const {
    return ".eetpadA eht fo roivaheb laicepS";
  }
};

/**
 * The Adapter makes the Adaptee's interface compatible with the Target's
 * interface.
 */
class Adapter : public Target {
 private:
  Adaptee *adaptee_;

 public:
  Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
  std::string Request() const override {
    std::string to_reverse = this->adaptee_->SpecificRequest();
    std::reverse(to_reverse.begin(), to_reverse.end());
    return "Adapter: (TRANSLATED) " + to_reverse;
  }
};

/**
 * The client code supports all classes that follow the Target interface.
 */
void ClientCode(const Target *target) {
  std::cout << target->Request();
}

int main() {
  std::cout << "Client: I can work just fine with the Target objects:\n";
  Target *target = new Target;
  ClientCode(target);
  std::cout << "\n\n";
  Adaptee *adaptee = new Adaptee;
  std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
  std::cout << "Adaptee: " << adaptee->SpecificRequest();
  std::cout << "\n\n";
  std::cout << "Client: But I can work with it via the Adapter:\n";
  Adapter *adapter = new Adapter(adaptee);
  ClientCode(adapter);
  std::cout << "\n";

  delete target;
  delete adaptee;
  delete adapter;

  return 0;
}

桥接

桥接是一种结构型设计模式, 可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。
层次结构中的第一层 (通常称为抽象部分) 将包含对第二层 (实现部分) 对象的引用。 抽象部分将能将一些 (有时是绝大部分) 对自己的调用委派给实现部分的对象。 所有的实现部分都有一个通用接口, 因此它们能在抽象部分内部相互替换。

/**
 * The Implementation defines the interface for all implementation classes. It
 * doesn't have to match the Abstraction's interface. In fact, the two
 * interfaces can be entirely different. Typically the Implementation interface
 * provides only primitive operations, while the Abstraction defines higher-
 * level operations based on those primitives.
 */

class Implementation {
 public:
  virtual ~Implementation() {}
  virtual std::string OperationImplementation() const = 0;
};

/**
 * Each Concrete Implementation corresponds to a specific platform and
 * implements the Implementation interface using that platform's API.
 */
class ConcreteImplementationA : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "ConcreteImplementationA: Here's the result on the platform A.\n";
  }
};
class ConcreteImplementationB : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "ConcreteImplementationB: Here's the result on the platform B.\n";
  }
};

/**
 * The Abstraction defines the interface for the "control" part of the two class
 * hierarchies. It maintains a reference to an object of the Implementation
 * hierarchy and delegates all of the real work to this object.
 */

class Abstraction {
  /**
   * @var Implementation
   */
 protected:
  Implementation* implementation_;

 public:
  Abstraction(Implementation* implementation) : implementation_(implementation) {
  }

  virtual ~Abstraction() {
  }

  virtual std::string Operation() const {
    return "Abstraction: Base operation with:\n" +
           this->implementation_->OperationImplementation();
  }
};
/**
 * You can extend the Abstraction without changing the Implementation classes.
 */
class ExtendedAbstraction : public Abstraction {
 public:
  ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
  }
  std::string Operation() const override {
    return "ExtendedAbstraction: Extended operation with:\n" +
           this->implementation_->OperationImplementation();
  }
};

/**
 * Except for the initialization phase, where an Abstraction object gets linked
 * with a specific Implementation object, the client code should only depend on
 * the Abstraction class. This way the client code can support any abstraction-
 * implementation combination.
 */
void ClientCode(const Abstraction& abstraction) {
  // ...
  std::cout << abstraction.Operation();
  // ...
}
/**
 * The client code should be able to work with any pre-configured abstraction-
 * implementation combination.
 */

int main() {
  Implementation* implementation = new ConcreteImplementationA;
  Abstraction* abstraction = new Abstraction(implementation);
  ClientCode(*abstraction);
  std::cout << std::endl;
  delete implementation;
  delete abstraction;

  implementation = new ConcreteImplementationB;
  abstraction = new ExtendedAbstraction(implementation);
  ClientCode(*abstraction);

  delete implementation;
  delete abstraction;

  return 0;
}

这里先暂时介绍这几种的模型,其他的模型如果以后用到的话会再进行添加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值