设计模式是软件设计中常见问题的典型解决方案。 每个模式就像一张蓝图, 你可以通过对其进行定制来解决代码中的特定设计问题。

一些基本概念

组合

在一个类中以另一个类的对象作为数据成员的,称为类的组合(composition)

绑定

函数体与函数调用关联起来叫做绑定
早绑定:早绑定发送在程序运行之前,也是编译和链接阶段
晚绑定:晚绑定发生在程序运行期间,主要体现在继承的多态方面
晚绑定优于早绑定运行时依赖优于编译时依赖
因为对于晚绑定,同一个函数可以实现不同功能, 大幅减少代码量并且代码可读性高。
不过对于早绑定,因为是在编译的时候就确定好了,因此性能比晚绑定好。

耦合

模块间的依赖性就是耦合
松耦合,就是联系越小越好,紧耦合反之。
松耦合优于紧耦合

钩子方法(hook)

抽象方法或者接口中定义的方法的一个空实现

protected boolean needCheckHomework(){return  false;}

遵循原则【*】

开闭原则

  • 对扩展开放,对修改关闭,需求改变增加功能的时候,原有的代码不变,增加新的扩展功能
  • 当软件需要变化时,尽量 通过扩展软件实体的行为来实现变化,而不是 通过修改已有的代码来实现变化。

代码只能往上加,不能修改原来写好已编译的代码

里式替换原则

  • 任何基类可以出现的地方,子类一定可以出现,对实现抽象化,所有引用基类的地方必须能透明地使用其子类的对象
  • 类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
  • 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法

用父类的地方均可以用子类替换

依赖倒置原则DIP

(Dependence Inversion Principle)

  • 是开闭原则的基础,针对接口编程,而不依赖于具体。 框架中常用的技术:java中Spring
  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒转(倒置)的中心思想是 面向接口编程

接口隔离原则ISP

(Interface-Segregation Principles)

  • 使用多个隔离的接口,要比使用单一的接口更好。出发点是降低耦合性,一个接口就负责一件事情
  • 客户端不应该依赖它不需要的接口,即 一个类对另一个类的依赖应该建立在最小的接口上
  • 类 A 通过接口 Interface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,如果接口 Interface1 对于类 A 和类 C 来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法。
  • 按隔离原则应当这样处理:
  • 将接口 Interface1 拆分为 独立的几个接口( 这里我们拆分成 3 个接口),类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则

迪米特原则DP

(Demeter Principle)

  • 最少知道原则,一个实体尽可能少的与其他实体发生相互作用,使模块功能相对独立【属性尽可能是私有的,通过setter,getter,只提供构造】。
  • 被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外泄露任何信息

合成复用原则CRP

(Composite Reuse Principle)

  • 能用组合完成的,就不要使用继承
  • 针对接口编程,而不是针对实现编程

单一职责原则SRP

(Single Responsibility Principle)

  • 就一个类而言,应该仅有一个引起他变化的原则

三类模式

  • 创建型模式:这类模式提供创建对象的机制, 能够提升已有代码的灵活性和可复用性。
  • 结构型模式:这类模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。
  • 行为型模式:这类模式负责对象间的高效沟通和职责委派。

简单工厂模式

这个模式不在23种里面。

工厂:一个单独的类来完成创造实例
比如对于一个计算器,有加减乘除的方法,我想要加一个sqrt的方法,实在工厂类中添加
目的:添加新的类,不会影响以前的代码。
后果:耦合性过高,并不满足开闭原则

https://juejin.cn/post/6844903700838744077

简单工厂类

public class OperationFactory {
    public static Operation createOperate(string operate) {
        Operation oper = null;
        switch (operate) {
            case "+":
                oper = new OperationAdd();
                break;
            case "-":
                oper = new OperationSub();
                break;
            case "*":
                oper = new OperationMul();
                break;
            case "/":
                oper = new OperationDiv();
                break;
        }
        return oper;
    }
}

GOF的23种模式

模板模式(Template)

行为型模式

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

目的:把不变行为搬移到超类,去除子类中的重复代码来体现优势。
实现:将通用算法抽象出来。
核心思路:在抽象类实现,其他步骤在子类实现。
实例:试卷复制

基类中存在纯虚函数的情况下无法被实例化,因为纯虚函数必须被重写。

简单的类继承

#include <iostream>

class AbstractClass {
public:
  void TemplateMethod() const {
    this->BaseOperation1();
    this->RequiredOperations1();
    this->BaseOperation2();
    this->Hook1();
    this->RequiredOperation2();
    this->BaseOperation3();
    this->Hook2();
  }

protected:
  void BaseOperation1() const { std::cout << "基类方法1\n"; }
  void BaseOperation2() const { std::cout << "基类方法2\n"; }
  void BaseOperation3() const { std::cout << "基类方法3\n"; }
  virtual void RequiredOperations1() const = 0;
  virtual void RequiredOperation2() const = 0;
  virtual void Hook1() const {}
  virtual void Hook2() const {}
};
class ConcreteClass1 : public AbstractClass {
protected:
  void RequiredOperations1() const override {
    std::cout << "1号子类重写了要求函数1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "1号子类重写了要求函数2\n";
  }
};
class ConcreteClass2 : public AbstractClass {
protected:
  void RequiredOperations1() const override {
    std::cout << "2号子类重写了要求函数1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "2号子类重写了要求函数2\n";
  }
  void Hook1() const override { std::cout << "2号子类重写了钩子函数1\n"; }
};
void ClientCode(AbstractClass *class_) { class_->TemplateMethod(); }

int main() {
  std::cout << "子类1定义\n";
  ConcreteClass1 *concreteClass1 = new ConcreteClass1;
  ClientCode(concreteClass1);
  std::cout << "\n";
  std::cout << "子类2定义\n";
  ConcreteClass2 *concreteClass2 = new ConcreteClass2;
  ClientCode(concreteClass2);
  delete concreteClass1;
  delete concreteClass2;
  return 0;
}

output

子类1定义
基类方法1
1号子类重写了要求函数1
基类方法2
1号子类重写了要求函数2
基类方法3

子类2定义
基类方法1
2号子类重写了要求函数1
基类方法2
2号子类重写了钩子函数1
2号子类重写了要求函数2
基类方法3

策略模式(Strategy)

行为型模式

它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

目的:算法的变化不会影响到在使用算法的客户。一个类的行为或算法可以在运行时修改。
实现:将算法的步骤封装,方便替换。
核心思路:将算法封装,任意替换,基于接口的实现而不是类的继承。
实例:商场促销,折扣满减算法。

可以和简单工厂模式组合使用。模板模式基于继承,策略模式基于组合,算法封装在类里,通过接口的改变选择。

算法经常要切换的时候使用

对一组数据的不同算法处理

#include <algorithm>
#include <iostream>
#include <vector>

class Strategy {
public:
  virtual ~Strategy() {}
  virtual std::string
  DoAlgorithm(const std::vector<std::string> &data) const = 0;
};

class Context {
private:
  Strategy *strategy_;

public:
  Context(Strategy *strategy = nullptr) : strategy_(strategy) {}
  ~Context() { delete this->strategy_; }
  void set_strategy(Strategy *strategy) {
    delete this->strategy_;
    this->strategy_ = strategy;
  }
  void DoSomeBusinessLogic() const {
    std::cout << "对于{a,b,c,d,e}这一组数据,我没有想好怎么处理\n";
    std::string result = this->strategy_->DoAlgorithm(
        std::vector<std::string>{"a", "e", "c", "b", "d"});
    std::cout << result << "\n";
  }
};

class ConcreteStrategyA : public Strategy {
public:
  std::string DoAlgorithm(const std::vector<std::string> &data) const override {
    std::cout << "现在是方法A" << std::endl;
    std::string result;
    std::for_each(std::begin(data), std::end(data),
                  [&result](const std::string &letter) { result += letter; });
    std::sort(std::begin(result), std::end(result));

    return result;
  }
};
class ConcreteStrategyB : public Strategy {
  std::string DoAlgorithm(const std::vector<std::string> &data) const override {
    std::cout << "现在是方法B" << std::endl;
    std::string result;
    std::for_each(std::begin(data), std::end(data),
                  [&result](const std::string &letter) { result += letter; });
    std::sort(std::begin(result), std::end(result));
    for (int i = 0; i < result.size() / 2; i++) {
      std::swap(result[i], result[result.size() - i - 1]);
    }

    return result;
  }
};

void ClientCode() {
  Context *context = new Context(new ConcreteStrategyA);
  std::cout << "A方法正序输出" << std::endl;
  context->DoSomeBusinessLogic();
  std::cout << "\n";
  std::cout << "B方法倒序输出" << std::endl;
  context->set_strategy(new ConcreteStrategyB);
  context->DoSomeBusinessLogic();
  delete context;
}

int main() {
  ClientCode();
  return 0;
}

output

A方法正序输出
对于{a,b,c,d,e}这一组数据,我没有想好怎么处理
现在是方法A
abcde

B方法倒序输出
对于{a,b,c,d,e}这一组数据,我没有想好怎么处理
现在是方法B
edcba

工厂模式(Factory)

创建型模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

目的:解决接口选择的问题,减少简单工厂模式的耦合性。
实现:让子类继承实现工厂接口,返回的也是抽象的产品。
核心思路:创建过程在其子类执行。
实例:数据库问题

计算器算法工厂

class AddFactory : IFactory
{
    public Operation CreateOperation()
    {
        return new OperationAdd();
    }
}
class SubFactory : IFactory
{
    public Operation CreateOperation()
    {
        return new OperationSub();
    }
}
class MulFactory : IFactory
{
    public Operation CreateOperation()
    {
        return new OperationMul();
    }
}
class DivFactory : IFactory
{
    public Operation CreateOperation()
    {
        return new OperationDiv();
    }
}

流水线工厂

#include <iostream>

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

class ConcreteProduct1 : public Product {
public:
  std::string Operation() const override { return "{产品1号}"; }
};
class ConcreteProduct2 : public Product {
public:
  std::string Operation() const override { return "{产品2号}"; }
};

class Creator {
public:
  virtual ~Creator(){};
  virtual Product *FactoryMethod() const = 0;
  std::string SomeOperation() const {
    Product *product = this->FactoryMethod();
    std::string result = "创造者: 已流水线生产 " + product->Operation();
    delete product;
    return result;
  }
};

class ConcreteCreator1 : public Creator {
public:
  Product *FactoryMethod() const override { return new ConcreteProduct1(); }
};

class ConcreteCreator2 : public Creator {
public:
  Product *FactoryMethod() const override { return new ConcreteProduct2(); }
};

void ClientCode(const Creator &creator) {
  std::cout << "客户端: 我不知道怎么生产,交给工厂了\n"
            << creator.SomeOperation() << std::endl;
}

int main() {
  std::cout << "App: 生产1号产品\n";
  Creator *creator = new ConcreteCreator1();
  ClientCode(*creator);
  std::cout << std::endl;
  std::cout << "App: 生产2号产品\n";
  Creator *creator2 = new ConcreteCreator2();
  ClientCode(*creator2);

  delete creator;
  delete creator2;
  return 0;
}

output

App: 生产1号产品
客户端: 我不知道怎么生产,交给工厂了
创造者: 已流水线生产 {产品1号}

App: 生产2号产品
客户端: 我不知道怎么生产,交给工厂了
创造者: 已流水线生产 {产品2号}

单例模式(Singleton)

创建型模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

目的:控制实例数目,节省系统资源
实现:判断系统是否已经有这个单例,如果有则返回,如果没有则创建
核心思路:构造函数是私有的
实例:数据库的链接,打印机多人共享

如果你创建了一个对象, 同时过一会儿后你决定再创建一个新对象, 此时你会获得之前已创建的对象, 而不是一个新对象。

#include <iostream>
#include <thread>

class Singleton {
protected:
  Singleton(const std::string value) : value_(value) {}
  static Singleton *singleton_;
  std::string value_;

public:
  Singleton(Singleton &other) = delete;
  void operator=(const Singleton &) = delete;

  static Singleton *GetInstance(const std::string &value);
  void SomeBusinessLogic() {}

  std::string value() const { return value_; }
};

Singleton *Singleton::singleton_ = nullptr;

Singleton *Singleton::GetInstance(const std::string &value) {
  if (singleton_ == nullptr) {
    singleton_ = new Singleton(value);
  }
  return singleton_;
}

void ThreadFoo() {
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  Singleton *singleton = Singleton::GetInstance("FOO");
  std::cout << singleton->value() << "\n";
}

void ThreadBar() {
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  Singleton *singleton = Singleton::GetInstance("BAR");
  std::cout << singleton->value() << "\n";
}

int main() {
  std::cout << "如果打印两个相同的值,说明单例被复用了\n"
            << "如果打印两个不同的值,说明创建了两个单例(单例模式多线程不安全"
               "的情况)\n\n"
            << "结果:\n";
  std::thread t1(ThreadFoo);
  std::thread t2(ThreadBar);
  t1.join();
  t2.join();

  return 0;
}

g++编译时加参数-lpthread

output

如果打印两个相同的值,说明单例被复用了
如果打印两个不同的值,说明创建了两个单例(单例模式多线程不安全的情况)

结果:
FOO
BAR

也有概率是这个结果

如果打印两个相同的值,说明单例被复用了
如果打印两个不同的值,说明创建了两个单例(单例模式多线程不安全的情况)

结果:
FOOFOO

抽象工厂模式(Abstract Factory)

创建型模式

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

目的:解决多个接口的选择问题
实现:在一个产品族里面,定义多个产品
核心思路:在一个工厂里聚合多个同类产品
实例:当系统里有多个数据库需要切换的时候。

多个工厂流水线生产

#include <iostream>

class AbstractProductA {
public:
  virtual ~AbstractProductA(){};
  virtual std::string UsefulFunctionA() const = 0;
};

class ConcreteProductA1 : public AbstractProductA {
public:
  std::string UsefulFunctionA() const override { return "产品A1"; }
};

class ConcreteProductA2 : public AbstractProductA {
  std::string UsefulFunctionA() const override { return "产品A2"; }
};

class AbstractProductB {
public:
  virtual ~AbstractProductB(){};
  virtual std::string UsefulFunctionB() const = 0;
  virtual std::string
  AnotherUsefulFunctionB(const AbstractProductA &collaborator) const = 0;
};

class ConcreteProductB1 : public AbstractProductB {
public:
  std::string UsefulFunctionB() const override { return "产品B1"; }
  std::string
  AnotherUsefulFunctionB(const AbstractProductA &collaborator) const override {
    const std::string result = collaborator.UsefulFunctionA();
    return "产品B1联合生产 ( " + result + " )";
  }
};

class ConcreteProductB2 : public AbstractProductB {
public:
  std::string UsefulFunctionB() const override { return "产品B2"; }
  std::string
  AnotherUsefulFunctionB(const AbstractProductA &collaborator) const override {
    const std::string result = collaborator.UsefulFunctionA();
    return "产品B2联合生产 ( " + result + " )";
  }
};

class AbstractFactory {
public:
  virtual AbstractProductA *CreateProductA() const = 0;
  virtual AbstractProductB *CreateProductB() const = 0;
};
class ConcreteFactory1 : public AbstractFactory {
public:
  AbstractProductA *CreateProductA() const override {
    return new ConcreteProductA1();
  }
  AbstractProductB *CreateProductB() const override {
    return new ConcreteProductB1();
  }
};

class ConcreteFactory2 : public AbstractFactory {
public:
  AbstractProductA *CreateProductA() const override {
    return new ConcreteProductA2();
  }
  AbstractProductB *CreateProductB() const override {
    return new ConcreteProductB2();
  }
};

void ClientCode(const AbstractFactory &factory) {
  const AbstractProductA *product_a = factory.CreateProductA();
  const AbstractProductB *product_b = factory.CreateProductB();
  std::cout << product_b->UsefulFunctionB() << "\n";
  std::cout << product_b->AnotherUsefulFunctionB(*product_a) << "\n";
  delete product_a;
  delete product_b;
}

int main() {
  std::cout << "客户端: 用第一个工厂生产\n";
  ConcreteFactory1 *f1 = new ConcreteFactory1();
  ClientCode(*f1);
  delete f1;
  std::cout << std::endl;
  std::cout << "客户端: 用第二个工厂生产\n";
  ConcreteFactory2 *f2 = new ConcreteFactory2();
  ClientCode(*f2);
  delete f2;
  return 0;
}

output

客户端: 用第一个工厂生产
产品B1
产品B1联合生产 ( 产品A1 )

客户端: 用第二个工厂生产
产品B2
产品B2联合生产 ( 产品A2 )

原型模式(Prototype)

创建型模式

用原型实例指定创建对象的种类,并且用过拷贝这些原型创建新的对象。

目的:创建一个对象非常的复杂的时候(很多参数),隐藏部分共同的数据。
实现:利用已有的一个原型对象,快速地生成和原型对象一样的实例。
核心思路:实现克隆操作,在 JAVA 继承 Cloneable,重写 clone()。
实例:简历拷贝,数据库拷贝修改。

注意浅拷贝和深拷贝,浅拷贝是一个引用,深拷贝是将结构数据全部拷贝成一个新的样本。

#include <iostream>
#include <unordered_map>

using std::string;

enum Type { PROTOTYPE_1 = 0, PROTOTYPE_2 };

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 << "调用来自 " << prototype_name_
              << " 的方法转变面积为 : " << prototype_field << std::endl;
  }
};

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) {}

  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); }
};

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);
  }

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

  Prototype *CreatePrototype(Type type) { return prototypes_[type]->Clone(); }
};

void Client(PrototypeFactory &prototype_factory) {
  std::cout << "原型1\n";

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

  std::cout << "\n";

  std::cout << "原型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;
}

output

原型1
调用来自 PROTOTYPE_1  的方法转变面积为 : 90

原型2
调用来自 PROTOTYPE_2  的方法转变面积为 : 10

建造者模式(Builder)

创造型模式

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

目的:创建一些复杂的对象,这些对象内部的构建面临复杂的变化
实现:将变与不变分离开
核心思路:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系
实例:做饭,一些步骤不可少,组装电脑

产品的制造

#include <iostream>
#include <vector>

class Product1 {
public:
  std::vector<std::string> parts_;
  void ListParts() const {
    std::cout << "产品模块: ";
    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";
  }
};

class Builder {
public:
  virtual ~Builder() {}
  virtual void ProducePartA() const = 0;
  virtual void ProducePartB() const = 0;
  virtual void ProducePartC() const = 0;
};
class ConcreteBuilder1 : public Builder {
private:
  Product1 *product;

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

  ~ConcreteBuilder1() { delete product; }

  void Reset() { this->product = new Product1(); }

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

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

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

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

class Director {
private:
  Builder *builder;

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

  void BuildMinimalViableProduct() { this->builder->ProducePartA(); }

  void BuildFullFeaturedProduct() {
    this->builder->ProducePartA();
    this->builder->ProducePartB();
    this->builder->ProducePartC();
  }
};
void ClientCode(Director &director) {
  ConcreteBuilder1 *builder = new ConcreteBuilder1();
  director.set_builder(builder);
  std::cout << "基础产品:\n";
  director.BuildMinimalViableProduct();

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

  std::cout << "完整产品:\n";
  director.BuildFullFeaturedProduct();

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

  // 建造者模式不一定需要指导类
  std::cout << "定制产品:\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;
}

output

基础产品:
产品模块: 模块A1

完整产品:
产品模块: 模块A1, 模块B1, 模块C1

定制产品:
产品模块: 模块A1, 模块C1

外观模式(Facade)

结构型模式

为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

目的:隐藏系统的复杂性,向客户端提供一个可以访问的统一接口
实现:客户端不与系统耦合,外观类与系统耦合
核心思路:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
实例:基金管理股票,医院挂号,JAVA三层模式

JavaEE中,Controller层到Service层再到DAO层,分层管理。

#include <iostream>

class Subsystem1 {
 public:
  std::string Operation1() const {
    return "子系统1: Ready!\n";
  }
  std::string OperationN() const {
    return "子系统1: Go!\n";
  }
};

class Subsystem2 {
 public:
  std::string Operation1() const {
    return "子系统2: Get ready!\n";
  }
  std::string OperationZ() const {
    return "子系统2: Fire!\n";
  }
};

class Facade {
 protected:
  Subsystem1 *subsystem1_;
  Subsystem2 *subsystem2_;
 public:
  Facade(
      Subsystem1 *subsystem1 = nullptr,
      Subsystem2 *subsystem2 = nullptr) {
    this->subsystem1_ = subsystem1 ?: new Subsystem1;
    this->subsystem2_ = subsystem2 ?: new Subsystem2;
  }
  ~Facade() {
    delete subsystem1_;
    delete subsystem2_;
  }
  std::string Operation() {
    std::string result = "Facade 初始化子系统:\n";
    result += this->subsystem1_->Operation1();
    result += this->subsystem2_->Operation1();
    result += "Facade 命令子系统执行操作:\n";
    result += this->subsystem1_->OperationN();
    result += this->subsystem2_->OperationZ();
    return result;
  }
};

void ClientCode(Facade *facade) {
  std::cout << facade->Operation();
}

int main() {
  Subsystem1 *subsystem1 = new Subsystem1;
  Subsystem2 *subsystem2 = new Subsystem2;
  Facade *facade = new Facade(subsystem1, subsystem2);
  ClientCode(facade);

  delete facade;

  return 0;
}

output

Facade 初始化子系统:
子系统1: Ready!
子系统2: Get ready!
Facade 命令子系统执行操作:
子系统1: Go!
子系统2: Fire!

桥接模式(Bridge)

结构型模式

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

目的:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活
实现:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合
核心思路:抽象类依赖实现类
实例:不同手机之间的软件开发,手机支付方式

#include <iostream>

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

class ConcreteImplementationA : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "具体实施A: 这是平台A.\n";
  }
};
class ConcreteImplementationB : public Implementation {
 public:
  std::string OperationImplementation() const override {
    return "具体实施B: 这是平台B.\n";
  }
};

class Abstraction {
 protected:
  Implementation* implementation_;

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

  virtual ~Abstraction() {
  }

  virtual std::string Operation() const {
    return "抽象类: 基类操作:\n" +
           this->implementation_->OperationImplementation();
  }
};
class ExtendedAbstraction : public Abstraction {
 public:
  ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
  }
  std::string Operation() const override {
    return "扩展抽象: 扩展操作:\n" +
           this->implementation_->OperationImplementation();
  }
};

void ClientCode(const Abstraction& abstraction) {
  std::cout << abstraction.Operation();
}

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;
}

output

抽象类: 基类操作:
具体实施A: 这是平台A.

扩展抽象: 扩展操作:
具体实施B: 这是平台B.

适配器模式(Adapter)

结构型模式

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

目的:作为两个不兼容的接口之间的桥梁。结合多个接口融合
实现:继承或依赖。在一个类上继承并调用。
核心思路:适配器继承或依赖已有的对象,实现想要的目标接口。
实例:翻译,电压适配器,虚拟机

#include <iostream>
#include <algorithm>

class Target {
 public:
  virtual ~Target() = default;

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

class Adaptee {
 public:
  std::string SpecificRequest() const {
    return ".eetpadA eht fo roivaheb laicepS";
  }
};

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: (翻译) " + to_reverse;
  }
};

void ClientCode(const Target *target) {
  std::cout << target->Request();
}

int main() {
  std::cout << "客户端: 我可以很好地处理目标对象:\n";
  Target *target = new Target;
  ClientCode(target);
  std::cout << "\n\n";
  Adaptee *adaptee = new Adaptee;
  std::cout << "客户端: Adaptee类有一个奇怪的接口。我不明白:\n";
  std::cout << "Adaptee: " << adaptee->SpecificRequest();
  std::cout << "\n\n";
  std::cout << "客户端: 但我可以通过适配器(Adapter)使用它:\n";
  Adapter *adapter = new Adapter(adaptee);
  ClientCode(adapter);
  std::cout << "\n";

  delete target;
  delete adaptee;
  delete adapter;

  return 0;
}

output

客户端: 我可以很好地处理目标对象:
Target: The default target's behavior.

客户端: Adaptee类有一个奇怪的接口。我不明白:
Adaptee: .eetpadA eht fo roivaheb laicepS

客户端: 但我可以通过适配器(Adapter)使用它:
Adapter: (翻译) Special behavior of the Adaptee.

组合模式(Composite)

结构型模式

将对象组合成树状结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

目的:把一组相似的对象当做一个单一的对象,创建类似于对象树的方式
实现:树枝和叶子实现统一接口,树枝内部组合该接口。
核心思路:树枝内部组合该接口,并且含有内部属性 List,里面放 Component
实例:层级办公管理系统,递归遍历目录

如果应用的核心模型能用树状结构表示, 在应用中使用组合模式才有价值

#include <algorithm>
#include <iostream>
#include <list>
#include <string>
class Component {
 protected:
  Component *parent_;

 public:
  virtual ~Component() {}
  void SetParent(Component *parent) {
    this->parent_ = parent;
  }
  Component *GetParent() const {
    return this->parent_;
  }
  virtual void Add(Component *component) {}
  virtual void Remove(Component *component) {}
  virtual bool IsComposite() const {
    return false;
  }
  virtual std::string Operation() const = 0;
};
class Leaf : public Component {
 public:
  std::string Operation() const override {
    return "Leaf";
  }
};
class Composite : public Component {
 protected:
  std::list<Component *> children_;

 public:
  void Add(Component *component) override {
    this->children_.push_back(component);
    component->SetParent(this);
  }
  void Remove(Component *component) override {
    children_.remove(component);
    component->SetParent(nullptr);
  }
  bool IsComposite() const override {
    return true;
  }
  std::string Operation() const override {
    std::string result;
    for (const Component *c : children_) {
      if (c == children_.back()) {
        result += c->Operation();
      } else {
        result += c->Operation() + "+";
      }
    }
    return "Branch(" + result + ")";
  }
};
void ClientCode(Component *component) {
  std::cout << "结果: " << component->Operation();
}
void ClientCode2(Component *component1, Component *component2) {
  if (component1->IsComposite()) {
    component1->Add(component2);
  }
  std::cout << "结果: " << component1->Operation();
}

int main() {
  Component *simple = new Leaf;
  std::cout << "客户端: 我有一个简单的组件:\n";
  ClientCode(simple);
  std::cout << "\n\n";

  Component *tree = new Composite;
  Component *branch1 = new Composite;

  Component *leaf_1 = new Leaf;
  Component *leaf_2 = new Leaf;
  Component *leaf_3 = new Leaf;
  branch1->Add(leaf_1);
  branch1->Add(leaf_2);
  Component *branch2 = new Composite;
  branch2->Add(leaf_3);
  tree->Add(branch1);
  tree->Add(branch2);
  std::cout << "客户端: 现在我有一个复合树:\n";
  ClientCode(tree);
  std::cout << "\n\n";

  std::cout << "客户端: 即使在管理树时,我也不需要检查组件类:\n";
  ClientCode2(tree, simple);
  std::cout << "\n";

  delete simple;
  delete tree;
  delete branch1;
  delete branch2;
  delete leaf_1;
  delete leaf_2;
  delete leaf_3;

  return 0;
}

output

客户端: 我有一个简单的组件:
结果: Leaf

客户端: 现在我有一个复合树:
结果: Branch(Branch(Leaf+Leaf)+Branch(Leaf))

客户端: 即使在管理树时,我也不需要检查组件类:
结果: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)

状态模式(State)

行为型模式

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

目的:行为不同的时候,调用同样的方法,实现不同操作
实现:将各种具体的状态类抽象出来。
核心思路:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。
案例:工作日程表,消息传递机制,渲染实现奇偶行不同布局,手机锁定\解锁模式的不同操作

#include <iostream>
#include <typeinfo>

class Context;

class State {
 protected:
  Context *context_;

 public:
  virtual ~State() {
  }

  void set_context(Context *context) {
    this->context_ = context;
  }

  virtual void Handle1() = 0;
  virtual void Handle2() = 0;
};

class Context {
 private:
  State *state_;

 public:
  Context(State *state) : state_(nullptr) {
    this->TransitionTo(state);
  }
  ~Context() {
    delete state_;
  }
  void TransitionTo(State *state) {
    std::cout << "文本: 过渡到 " << typeid(*state).name() << ".\n";
    if (this->state_ != nullptr)
      delete this->state_;
    this->state_ = state;
    this->state_->set_context(this);
  }
  void Request1() {
    this->state_->Handle1();
  }
  void Request2() {
    this->state_->Handle2();
  }
};

class ConcreteStateA : public State {
 public:
  void Handle1() override;

  void Handle2() override {
    std::cout << "具体状态A 执行操作2.\n";
  }
};

class ConcreteStateB : public State {
 public:
  void Handle1() override {
    std::cout << "具体状态B 执行操作1.\n";
  }
  void Handle2() override {
    std::cout << "具体状态B 执行操作2.\n";
    std::cout << "具体状态B 想要改变文本状态.\n";
    this->context_->TransitionTo(new ConcreteStateA);
  }
};

void ConcreteStateA::Handle1() {
  {
    std::cout << "具体状态A 执行操作1.\n";
    std::cout << "具体状态A 想要改变文本状态.\n";

    this->context_->TransitionTo(new ConcreteStateB);
  }
}

void ClientCode() {
  Context *context = new Context(new ConcreteStateA);
  context->Request1();
  context->Request2();
  delete context;
}

int main() {
  ClientCode();
  return 0;
}

状态之间的切换在类中操作

output

文本: 过渡到 14ConcreteStateA.
具体状态A 执行操作1.
具体状态A 想要改变文本状态.
文本: 过渡到 14ConcreteStateB.
具体状态B 执行操作2.
具体状态B 想要改变文本状态.
文本: 过渡到 14ConcreteStateA.

观察者模式(Observer)

行为型模式

让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

目的:信息发布者,信息更新之后, 让所有的订阅者能够实时获取状态信息
实现:使用面向对象技术,将这种依赖关系弱化。
核心思路:在抽象类里有一个 ArrayList 存放观察者们
实例:放风通知,压缩和分割文件的进度

#include <iostream>
#include <list>
#include <string>

class IObserver {
 public:
  virtual ~IObserver(){};
  virtual void Update(const std::string &message_from_subject) = 0;
};

class ISubject {
 public:
  virtual ~ISubject(){};
  virtual void Attach(IObserver *observer) = 0;
  virtual void Detach(IObserver *observer) = 0;
  virtual void Notify() = 0;
};

class Subject : public ISubject {
 public:
  virtual ~Subject() {
    std::cout << "Goodbye, I was the Subject.\n";
  }

  void Attach(IObserver *observer) override {
    list_observer_.push_back(observer);
  }
  void Detach(IObserver *observer) override {
    list_observer_.remove(observer);
  }
  void Notify() override {
    std::list<IObserver *>::iterator iterator = list_observer_.begin();
    HowManyObserver();
    while (iterator != list_observer_.end()) {
      (*iterator)->Update(message_);
      ++iterator;
    }
  }

  void CreateMessage(std::string message = "Empty") {
    this->message_ = message;
    Notify();
  }
  void HowManyObserver() {
    std::cout << "There are " << list_observer_.size() << " observers in the list.\n";
  }

  void SomeBusinessLogic() {
    this->message_ = "change message message";
    Notify();
    std::cout << "I'm about to do some thing important\n";
  }

 private:
  std::list<IObserver *> list_observer_;
  std::string message_;
};

class Observer : public IObserver {
 public:
  Observer(Subject &subject) : subject_(subject) {
    this->subject_.Attach(this);
    std::cout << "Hi, I'm the Observer \"" << ++Observer::static_number_ << "\".\n";
    this->number_ = Observer::static_number_;
  }
  virtual ~Observer() {
    std::cout << "Goodbye, I was the Observer \"" << this->number_ << "\".\n";
  }

  void Update(const std::string &message_from_subject) override {
    message_from_subject_ = message_from_subject;
    PrintInfo();
  }
  void RemoveMeFromTheList() {
    subject_.Detach(this);
    std::cout << "Observer \"" << number_ << "\" removed from the list.\n";
  }
  void PrintInfo() {
    std::cout << "Observer \"" << this->number_ << "\": a new message is available --> " << this->message_from_subject_ << "\n";
  }

 private:
  std::string message_from_subject_;
  Subject &subject_;
  static int static_number_;
  int number_;
};

int Observer::static_number_ = 0;

void ClientCode() {
  Subject *subject = new Subject;
  Observer *observer1 = new Observer(*subject);
  Observer *observer2 = new Observer(*subject);
  Observer *observer3 = new Observer(*subject);
  Observer *observer4;
  Observer *observer5;

  subject->CreateMessage("Hello World! :D");
  observer3->RemoveMeFromTheList();

  subject->CreateMessage("The weather is hot today! :p");
  observer4 = new Observer(*subject);

  observer2->RemoveMeFromTheList();
  observer5 = new Observer(*subject);

  subject->CreateMessage("My new car is great! ;)");
  observer5->RemoveMeFromTheList();

  observer4->RemoveMeFromTheList();
  observer1->RemoveMeFromTheList();

  delete observer5;
  delete observer4;
  delete observer3;
  delete observer2;
  delete observer1;
  delete subject;
}

int main() {
  ClientCode();
  return 0;
}

output

Hi, I'm the Observer "1".
Hi, I'm the Observer "2".
Hi, I'm the Observer "3".
There are 3 observers in the list.
Observer "1": a new message is available --> Hello World! :D
Observer "2": a new message is available --> Hello World! :D
Observer "3": a new message is available --> Hello World! :D
Observer "3" removed from the list.
There are 2 observers in the list.
Observer "1": a new message is available --> The weather is hot today! :p
Observer "2": a new message is available --> The weather is hot today! :p
Hi, I'm the Observer "4".
Observer "2" removed from the list.
Hi, I'm the Observer "5".
There are 3 observers in the list.
Observer "1": a new message is available --> My new car is great! ;)
Observer "4": a new message is available --> My new car is great! ;)
Observer "5": a new message is available --> My new car is great! ;)
Observer "5" removed from the list.
Observer "4" removed from the list.
Observer "1" removed from the list.
Goodbye, I was the Observer "5".
Goodbye, I was the Observer "4".
Goodbye, I was the Observer "3".
Goodbye, I was the Observer "2".
Goodbye, I was the Observer "1".
Goodbye, I was the Subject.

装饰器模式(Decorator)

结构型模式

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。

目的:将对象本身和附加的信息实现分离。为已有功能动态地添加更多功能的一种方式。
实现:将要装饰的功能分别放在单独的类中,并让这个类包装它要装饰的对象。
核心思路:当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
案例:按顺序装扮衣服。加密数据,文件流。

顺序非常重要

#include <iostream>

class Component {
 public:
  virtual ~Component() {}
  virtual std::string Operation() const = 0;
};

class ConcreteComponent : public Component {
 public:
  std::string Operation() const override {
    return "具体组件";
  }
};

class Decorator : public Component {

 protected:
  Component* component_;

 public:
  Decorator(Component* component) : component_(component) {
  }

  std::string Operation() const override {
    return this->component_->Operation();
  }
};

class ConcreteDecoratorA : public Decorator {

 public:
  ConcreteDecoratorA(Component* component) : Decorator(component) {
  }
  std::string Operation() const override {
    return "具体装饰A(" + Decorator::Operation() + ")";
  }
};

class ConcreteDecoratorB : public Decorator {
 public:
  ConcreteDecoratorB(Component* component) : Decorator(component) {
  }

  std::string Operation() const override {
    return "具体装饰B(" + Decorator::Operation() + ")";
  }
};

void ClientCode(Component* component) {
  std::cout << "结果: " << component->Operation();
}

int main() {
  Component* simple = new ConcreteComponent;
  std::cout << "客户端: 我有一个简单的组件:\n";
  ClientCode(simple);
  std::cout << "\n\n";
  Component* decorator1 = new ConcreteDecoratorA(simple);
  Component* decorator2 = new ConcreteDecoratorB(decorator1);
  std::cout << "客户端: 现在我有了一个装饰过的组件:\n";
  ClientCode(decorator2);
  std::cout << "\n";

  delete simple;
  delete decorator1;
  delete decorator2;

  return 0;
}

output

客户端: 我有一个简单的组件:
结果: 具体组件

客户端: 现在我有了一个装饰过的组件:
结果: 具体装饰B(具体装饰A(具体组件))

代理模式(Proxy)

为其他对象提供一种代理以控制对这个对象的访问。

目的:对于复杂 或者不方便的操作,通过代理者实现并且对功能进行增强
实现:代理类保存一个引用使得代理可以访问实体,并提供一个接口,可以用来替代实体。
核心思路:增加一个中间层,实现与被代理类组合
案例:快捷方式,中介,代理服务器

#include <iostream>

class Subject {
 public:
  virtual void Request() const = 0;
};

class RealSubject : public Subject {
 public:
  void Request() const override {
    std::cout << "实际工程: 处理请求.\n";
  }
};

class Proxy : public Subject {

 private:
  RealSubject *real_subject_;

  bool CheckAccess() const {
    // Some real checks should go here.
    std::cout << "代理: 在触发实际请求之前检查访问.\n";
    return true;
  }
  void LogAccess() const {
    std::cout << "代理: 记录请求的时间.\n";
  }

 public:
  Proxy(RealSubject *real_subject) : real_subject_(new RealSubject(*real_subject)) {
  }

  ~Proxy() {
    delete real_subject_;
  }

  void Request() const override {
    if (this->CheckAccess()) {
      this->real_subject_->Request();
      this->LogAccess();
    }
  }
};

void ClientCode(const Subject &subject) {
  subject.Request();
}

int main() {
  std::cout << "客户端: 使用实际工程执行客户代码:\n";
  RealSubject *real_subject = new RealSubject;
  ClientCode(*real_subject);
  std::cout << "\n";
  std::cout << "客户端: 用代理执行客户代码:\n";
  Proxy *proxy = new Proxy(real_subject);
  ClientCode(*proxy);

  delete real_subject;
  delete proxy;
  return 0;
}

output

客户端: 使用实际工程执行客户代码:
实际工程: 处理请求.

客户端: 用代理执行客户代码:
代理: 在触发实际请求之前检查访问.
实际工程: 处理请求.
代理: 记录请求的时间.

备忘录模式(Memento)

行为型模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外存储这个状态。这样就可以在某个时候恢复到原先保存的状态。

目的:保存对象的状态
实现:通过一个备忘录类专门存储对象状态
核心思路:客户不与备忘录类耦合,与备忘录管理类耦合
案例:游戏存档,数据备份。

#include <iostream>
#include <vector>
#include <ctime>

class Memento {
 public:
  virtual std::string GetName() const = 0;
  virtual std::string date() const = 0;
  virtual std::string state() const = 0;
};

class ConcreteMemento : public Memento {
 private:
  std::string state_;
  std::string date_;

 public:
  ConcreteMemento(std::string state) : state_(state) {
    this->state_ = state;
    std::time_t now = std::time(0);
    this->date_ = std::ctime(&now);
  }
  std::string state() const override {
    return this->state_;
  }
  std::string GetName() const override {
    return this->date_ + " / (" + this->state_.substr(0, 9) + "...)";
  }
  std::string date() const override {
    return this->date_;
  }
};

class Originator {
 private:
  std::string state_;

  std::string GenerateRandomString(int length = 10) {
    const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    int stringLength = sizeof(alphanum) - 1;

    std::string random_string;
    for (int i = 0; i < length; i++) {
      random_string += alphanum[std::rand() % stringLength];
    }
    return random_string;
  }

 public:
  Originator(std::string state) : state_(state) {
    std::cout << "发起人: 我的初始状态: " << this->state_ << "\n";
  }
  void DoSomething() {
    std::cout << "发起人: 我在做一些重要的事情.\n";
    this->state_ = this->GenerateRandomString(30);
    std::cout << "发起人: 我的状态切换至: " << this->state_ << "\n";
  }

  Memento *Save() {
    return new ConcreteMemento(this->state_);
  }
  void Restore(Memento *memento) {
    this->state_ = memento->state();
    std::cout << "发起人: 我的状态切换至: " << this->state_ << "\n";
  }
};

class Caretaker {
 private:
  std::vector<Memento *> mementos_;

  Originator *originator_;

 public:
  Caretaker(Originator *originator) : originator_(originator) {
    this->originator_ = originator;
  }

  void Backup() {
    std::cout << "\n看门人: 保存发起人的状态...\n";
    this->mementos_.push_back(this->originator_->Save());
  }
  void Undo() {
    if (!this->mementos_.size()) {
      return;
    }
    Memento *memento = this->mementos_.back();
    this->mementos_.pop_back();
    std::cout << "看门人: 恢复状态至: " << memento->GetName() << "\n";
    try {
      this->originator_->Restore(memento);
    } catch (...) {
      this->Undo();
    }
  }
  void ShowHistory() const {
    std::cout << "看门人: 这是备忘录的单子:\n";
    for (Memento *memento : this->mementos_) {
      std::cout << memento->GetName() << "\n";
    }
  }
};

void ClientCode() {
  Originator *originator = new Originator("Super-duper-super-puper-super.");
  Caretaker *caretaker = new Caretaker(originator);
  caretaker->Backup();
  originator->DoSomething();
  caretaker->Backup();
  originator->DoSomething();
  caretaker->Backup();
  originator->DoSomething();
  std::cout << "\n";
  caretaker->ShowHistory();
  std::cout << "\n客户端: 让我们回滚!\n\n";
  caretaker->Undo();
  std::cout << "\n客户端: 再来一次!\n\n";
  caretaker->Undo();

  delete originator;
  delete caretaker;
}

int main() {
  std::srand(static_cast<unsigned int>(std::time(NULL)));
  ClientCode();
  return 0;
}

output

发起人: 我的初始状态: Super-duper-super-puper-super.

看门人: 保存发起人的状态...
发起人: 我在做一些重要的事情.
发起人: 我的状态切换至: Du8ZomjnPvbYI8ZG3ksusN1lJqDqDK

看门人: 保存发起人的状态...
发起人: 我在做一些重要的事情.
发起人: 我的状态切换至: 9OEHy24fnRYNxqTW4WFxQ7IQsZG4PS

看门人: 保存发起人的状态...
发起人: 我在做一些重要的事情.
发起人: 我的状态切换至: OWqcnmdpROGzjDnCisgvn525Vuely1

看门人: 这是备忘录的单子:
Tue Dec 28 09:54:46 2021
 / (Super-dup...)
Tue Dec 28 09:54:46 2021
 / (Du8ZomjnP...)
Tue Dec 28 09:54:46 2021
 / (9OEHy24fn...)

客户端: 让我们回滚!

看门人: 恢复状态至: Tue Dec 28 09:54:46 2021
 / (9OEHy24fn...)
发起人: 我的状态切换至: 9OEHy24fnRYNxqTW4WFxQ7IQsZG4PS

客户端: 再来一次!

看门人: 恢复状态至: Tue Dec 28 09:54:46 2021
 / (Du8ZomjnP...)
发起人: 我的状态切换至: Du8ZomjnPvbYI8ZG3ksusN1lJqDqDK

迭代器模式(Iterator)

行为型模式

提供一种方法顺序访问一个聚合对象中各个元素,而又不是暴露该对象的内部表示。

目的:把在元素之间游走的责任交给迭代器,而不是聚合对象
实现:遍历一个聚合对象。
核心思路:定义接口:hasNext, next
案例JAVA 中的 Iterator

#include <iostream>
#include <string>
#include <vector>

template <typename T, typename U>
class Iterator {
 public:
  typedef typename std::vector<T>::iterator iter_type;
  Iterator(U *p_data, bool reverse = false) : m_p_data_(p_data) {
    m_it_ = m_p_data_->m_data_.begin();
  }

  void First() {
    m_it_ = m_p_data_->m_data_.begin();
  }

  void Next() {
    m_it_++;
  }

  bool IsDone() {
    return (m_it_ == m_p_data_->m_data_.end());
  }

  iter_type Current() {
    return m_it_;
  }

 private:
  U *m_p_data_;
  iter_type m_it_;
};

template <class T>
class Container {
  friend class Iterator<T, Container>;

 public:
  void Add(T a) {
    m_data_.push_back(a);
  }

  Iterator<T, Container> *CreateIterator() {
    return new Iterator<T, Container>(this);
  }

 private:
  std::vector<T> m_data_;
};

class Data {
 public:
  Data(int a = 0) : m_data_(a) {}

  void set_data(int a) {
    m_data_ = a;
  }

  int data() {
    return m_data_;
  }

 private:
  int m_data_;
};

void ClientCode() {
  std::cout << "________________Iterator with int______________________________________" << std::endl;
  Container<int> cont;

  for (int i = 0; i < 10; i++) {
    cont.Add(i);
  }

  Iterator<int, Container<int>> *it = cont.CreateIterator();
  for (it->First(); !it->IsDone(); it->Next()) {
    std::cout << *it->Current() << std::endl;
  }

  Container<Data> cont2;
  Data a(100), b(1000), c(10000);
  cont2.Add(a);
  cont2.Add(b);
  cont2.Add(c);

  std::cout << "________________Iterator with custom Class______________________________" << std::endl;
  Iterator<Data, Container<Data>> *it2 = cont2.CreateIterator();
  for (it2->First(); !it2->IsDone(); it2->Next()) {
    std::cout << it2->Current()->data() << std::endl;
  }
  delete it;
  delete it2;
}

int main() {
  ClientCode();
  return 0;
}

output

________________Iterator with int______________________________________
0
1
2
3
4
5
6
7
8
9
________________Iterator with custom Class______________________________
100
1000
10000

其他模式

MVC模式(Model-View-Controller)

这种模式用于应用程序的分层开发

  • Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  • View(视图) - 视图代表模型包含的数据的可视化。
  • Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

参考资料:
https://www.runoob.com/design-pattern/design-pattern-tutorial.html
https://refactoringguru.cn/design-patterns