读《大话设计模式》

ref

c++解决vscode cmd 输出中文乱码
system(“chcp 65001\n”); // Execute command line command chcp 65001

uml类图

设计模式

  • 创建型模式: 单例, 原型, 工厂方法, 抽象工厂, 建造者
    • 隐藏了这些类的实例如何创建, 系统关于对象所知道的是由抽象类所定义的接口, 提供了灵活性
  • 结构型模式: 代理, 适配器, 桥接, 装饰, 外观, 享元, 组合
  • 行为型模式: 模板方法, 策略, 命令, 职责链, 状态, 观察者, 中介者, 迭代器, 访问者, 备忘录, 解释器

1. 简单工厂模式

  • 不是GoF设计模式中正式的一员, 被认为是设计模式的起点
  • 通过一个专门的类(工厂类)来创建产品对象, 客户端通过工厂类的静态/非静态方法传入参数, 工厂类根据参数决定创建什么产品
  • 优点: 对象的创建和使用进行分离, 客户端无需关心具体产品实现, 只需知道产品接口
  • 缺点: 增加新产品时需修改工厂类代码, 不符合开闭原则

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;

class Operation {  //  运算基类
private:
  double _numberA = 0;
  double _numberB = 0;
public:
  double GetA() { return _numberA; }
  double GetB() { return _numberB; }
  void SetA(double tmp) { _numberA = tmp; }
  void SetB(double tmp) { _numberB = tmp; }
  virtual double GetResult(){
    double result = 0;
    return result;
  }
};
class OpAdd : public Operation {  //  加法类
public:
  double GetResult() override {
    double result = GetA() + GetB();
    return result;
  }
};
class OpSub : public Operation {  //  减法类
public:
  double GetResult() override {
    double result = GetA() - GetB();
    return result;
  }
};
class OpMul : public Operation {  //  乘法类
public:
  double GetResult() override {
    double result = GetA() * GetB();
    return result;
  }
};
class OpDiv : public Operation {  //  除法类
public:
  double GetResult() override {
    double result = GetB()==0 ? 0 : GetA() / GetB();
    return result;
  }
};

class OperationFactory{ //  运算工厂类
public:
  static Operation* createOperate(char operate){
    Operation* oper;
    switch (operate)
    {
    case '+': oper = new OpAdd; break;
    case '-': oper = new OpSub; break;
    case '*': oper = new OpMul; break;
    case '/': oper = new OpDiv; break;
    default: break;
    }
    return oper;
  }
};

int main()
{
  Operation* oper = OperationFactory::createOperate('/');
  oper->SetA(29);
  oper->SetB(36);
  cout << oper->GetResult();
}

2. 策略模式

  • 定义一系列算法的方法, 以相同的方式调用所有算法(殊途同归), 减少各种算法类和使用算法类之间的耦合
  • 优点
    • 有助于析取这些算法的公共功能
    • 简化了单元测试

在这里插入图片描述

#include<iostream>
using namespace std;

class CashSuper {
  double _result;
public:
  virtual double acceptCash(double money) {
    double result = money;
    return result;
  }
};

class CashNormal : public CashSuper {
public:
  double acceptCash(double money) override {
    double result = money;
    return result;
  }
};

class CashRebate : public CashSuper {   //  折扣策略
  double _discount;
public:
  CashRebate(double discount){
    _discount = discount;
  }
  double acceptCash(double money) override {
    double result = money*_discount;
    return result;
  }
};

class CashReturn : public CashSuper {   //  满减策略
  double _over;
  double _sub;
public:
  CashReturn(double over, double sub){
    _over = over;
    _sub = sub;
  }
  double acceptCash(double money) override {
    double result = money>=_over?(money-_sub):money;
    return result;
  }
};

enum STRATEGY{
  normal = 0,
  over300sub100,
  mul080
};

class CashContext {
  CashSuper* _cs;
public:
  CashContext(STRATEGY strategy){  //  传入具体收费策略
    switch (strategy)
    {
    case normal:
      _cs = new CashNormal();
      break;
    case over300sub100:
      _cs = new CashReturn(300, 100);
      break;
    case mul080:
      _cs = new CashRebate(0.8);
      break;
    default:break;
    }
  }
  double GetResult(double money){
    return _cs->acceptCash(money);
  }
};

int main()
{
  double total = 0.0f;
  CashContext cashCount(over300sub100);
  cout << cashCount.GetResult(800);
}

3. 单一职责原则

开放-封闭原则

  • 对扩展开放, 对更改封闭

依赖倒转原则

  1. 高层模块不应该依赖低层模块, 两个都应该依赖抽象
  2. 抽象不应该依赖细节, 细节应该依赖抽象 ( 针对接口编程, 不对实现编程)
  • 里氏代换原则: 软件不分辨父类对象和子类对象, 子类型必须能替换其父类型

6. 装饰模式

  • 动态地给一个对象添加额外的职责
  • 有效地把类的核心职责和装饰功能区分开, 去除重复装饰逻辑

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class Person{
private:
  string _name;
public:
  Person(){}
  Person(string name){
    this->_name = name;
  }
  ~Person(){}
  string Name(){
    return this->_name;
  }
  virtual void Show(){
    cout << _name << " 穿了" ;
  }
};
class Finery : public Person{
protected:
  Person* _component;
public:
  void Decorate(Person* component){
    _component = component;
  }
  void Show() override{
    _component->Show();
  }
};
class F_TShirt : public Finery{
public:
  void Decorate(Person* component){
    _component = component;
  }
  void Show() override{
    _component->Show();
    cout << " TShirt";
  }
};
class F_BigTrouser : public Finery{
public:
  void Decorate(Person* component){
    _component = component;
  }
  void Show() override{
    _component->Show();
    cout << " 跨裤";
  }
};

int main()
{
  Person* ZiLu = new Person("子路");
  F_TShirt* ts = new F_TShirt;
  F_BigTrouser* bt = new F_BigTrouser;
  ts->Decorate(ZiLu);
  bt->Decorate(ts);
  bt->Show();
  delete ZiLu, ts, bt;
}

7. 代理模式

  • 应用
    • 远程代理: 为一个对象在不同地址空间提供局部代表, 隐藏它在不同地址空间的事实(vpn)
    • 虚拟代理: 根据需要创建开销很大的对象, 通过其存放实例化需要长时间的真实对象(网页先加载文字后加载图片)
    • 安全代理: 控制真实对象访问时的权限(对象应有不同访问权限)
    • 智能指引: 调用真实对象时, 代理处理另外一些事
      在这里插入图片描述

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class Girl{
  string _name;
public:
  Girl(string name) : _name(name) {}
};
// 实体和代理共用接口
class IGiveGift{
  virtual void GiveGift(){}
};
// Proxy代表的真实实体
class Pursuit : public IGiveGift{
  Girl* _pljj;
public:
  Pursuit(Girl* pljj) : _pljj(pljj) {}
  void GiveGift() override{
    cout << "送礼1";
  }
};
//  保存一个引用使代理可访问实体, 提供一个Subject接口相同的接口, 这样代理可替代实体
class Proxy : public IGiveGift{ 
  Pursuit* _plgg;
public:
  Proxy(Girl* pljj) {
    _plgg = new Pursuit(pljj);
  }
  void GiveGift() override{
    _plgg->GiveGift();
  }
};
int main()
{
  Girl* jiejie = new Girl("李姐");
  Pursuit* tiangou = new Pursuit(jiejie);
  tiangou->GiveGift();
  Proxy* haoxiongdi = new Proxy(jiejie);
  haoxiongdi->GiveGift();
}

8. 工厂方法模式

  • 定义一个用于创建对象的接口, 让子类决定实例化哪个类
  • 优点: 符合开闭原则, 新增产品只需添加新工厂类不修改已有代码
  • 缺点: 客户端需要知道具体工厂类,

在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;

class Operation {  //  运算基类
private:
  double _numberA = 0;
  double _numberB = 0;
public:
  double GetA() { return _numberA; }
  double GetB() { return _numberB; }
  void SetA(double tmp) { _numberA = tmp; }
  void SetB(double tmp) { _numberB = tmp; }
  virtual double GetResult(){
    double result = 0;
    return result;
  }
};
class OpAdd : public Operation {  //  加法类
public:
  double GetResult() override {
    double result = GetA() + GetB();
    return result;
  }
};
class OpSub : public Operation {  //  减法类
public:
  double GetResult() override {
    double result = GetA() - GetB();
    return result;
  }
};
class OpMul : public Operation {  //  乘法类
public:
  double GetResult() override {
    double result = GetA() * GetB();
    return result;
  }
};
class OpDiv : public Operation {  //  除法类
public:
  double GetResult() override {
    double result = GetB()==0 ? 0 : GetA() / GetB();
    return result;
  }
};

class IFactory{ //  运算工厂类
public:
  virtual Operation* createOperate(){
    return nullptr;
  }
};

class AddFactory : public IFactory{
public:
  Operation* createOperate() override{
    return new OpAdd;
  }
};
class SubFactory : public IFactory{
public:
  Operation* createOperate() override{
    return new OpSub;
  }
};
class MulFactory : public IFactory{
public:
  Operation* createOperate() override{
    return new OpMul;
  }
};
class DivFactory : public IFactory{
public:
  Operation* createOperate() override{
    return new OpDiv;
  }
};

int main()
{
  IFactory* operFactory = new DivFactory();
  Operation* oper = operFactory->createOperate();
  oper->SetA(67.29);
  oper->SetB(22);
  cout << oper->GetResult();
}

9. 原型模式

  • 用原型实例指定创建对象的种类, 通过拷贝这些原型创建新的对象
  • (从一个对象再创建另一个可定制的对象, 且无需知道任何创建细节)

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;
typedef enum {
  MAN = 0,
  WOMAN = 1
}SEX;

class Resume{
 string _name;
 SEX _sex;
 int _age;
public:
  Resume(string name) : _name(name) {}
  void SetInfo(SEX sex, int age){
    _sex = sex;
    _age = age;
  }
  void Show(){
    cout << _name << ' ' << (_sex==0?"男":"女") << ' ' << _age << endl;
  }
  Resume* Clone(string name){
    Resume* people = new Resume(name);
    return people;
  }
};

int main()
{
  Resume* zhangsan = new Resume("张三");
  zhangsan->SetInfo(MAN, 23);
  zhangsan->Show();
  Resume* lisi = zhangsan->Clone("李四");
  lisi->SetInfo(WOMAN, 25);
  lisi->Show();
}

10. 模板方法模式

  • 将不变行为搬移到父类, 去除子类的重复代码

在这里插入图片描述


迪米特法则

  • 最少知识原则: 如果两个类不必彼此通信, 两个类就不应发生直接的相互作用. 若一个类需调用另一个类某方法, 可通过第三者转发该调用

12. 外观模式

  • 为子系统的一组接口提供一个一致的界面, 让其更容易使用

在这里插入图片描述


13. 建造者模式

  • (生成器模式):将一个产品的内部表象与生成过程分开, 用户只需指定需要建造的类型, 无需知道具体建造过程和细节
  • 应用: 创建一些复杂的对象, 这些对象内部构件建造顺序很稳定, 但对象内部构建常面临复杂的变化

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class Builder{
public:
  virtual void BuildHead(){}
  virtual void BuildBody(){}
  virtual void BuildLegs(){}
};

class MkTall : public Builder{
public:
  void BuildHead() override{
    cout << "长型脸 ";
  }
  void BuildBody() override{
    cout << "排骨 ";
  }
  void BuildLegs() override{
    cout << "大长腿 ";
  }
};

class MkShort : public Builder{
public:
  void BuildHead() override{
    cout << "方形脸 ";
  }
  void BuildBody() override{
    cout << "96块腹肌 ";
  }
  void BuildLegs() override{
    cout << "肌肉腿 ";
  }
};

class Director{
public:
  void Construct(Builder* builder){
    builder->BuildHead();
    builder->BuildBody();
    builder->BuildLegs();
    cout << endl;
  }
};

int main()
{
  MkTall* tall = new MkTall;
  MkShort* shor = new MkShort;
  Director leader;
  leader.Construct(tall);
  leader.Construct(shor);
}

14. 观察者模式

  • 发布-订阅(Publish/Subscribe)模式, 定义了一种一对多的依赖关系, 让多个观察者同时监听某对象, 对象变化时通知所有观察者
  • 特点: 解耦, subject改变, 所有Observer都得到通知

在这里插入图片描述

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

// void (*ptrMethod)();
class Observer;

class Notifier{
protected:
  vector<Observer*> notDetect;
  vector<Observer*> Detect;
public:
  virtual void Notify() = 0;
};

class Observer{
protected:
  string _name;
  Notifier* _sub;
public:
  Observer(string name, Notifier* sub) : _name(name),_sub(sub) {}
};

class ObsStock : public Observer{
public:
  ObsStock(string name, Notifier* sub) : Observer(name, sub) {}
  void UpdateGood(){
    cout << this->_name << " 及时关掉广发证券, 继续debug\n";
  }
  void UpdateBad(){
    cout << this->_name << " 没关掉广发证券, 扣钱\n";
  }
};

class ObsGame : public Observer{
public:
  ObsGame(string name, Notifier* sub) : Observer(name, sub) {}
  void UpdateGood(){
    cout << this->_name << " 及时关掉老头环, 继续debug\n";
  }
  void UpdateBad(){
    cout << this->_name << " 没关掉老头环, 扣钱\n";
  }
};

class Boss : public Notifier{
public:
  vector<function<void()>> eventGood;
  vector<function<void()>> eventBad;
  void Notify(){
    // myEvent();
    for(auto it:eventGood){
      it();
    }
    for(auto it:eventBad){
      it();
    }
  }
};

int main()
{
  Boss* LaoBan = new Boss;
  ObsStock* ChaoGu = new ObsStock("韭菜", LaoBan);
  ObsGame* DaJi = new ObsGame("彩笔", LaoBan);

  LaoBan->eventGood.push_back(bind(&ObsStock::UpdateGood, ChaoGu));
  LaoBan->eventGood.push_back(bind(&ObsGame::UpdateGood, DaJi));
  LaoBan->eventBad.push_back(bind(&ObsStock::UpdateBad, ChaoGu));
  LaoBan->eventBad.push_back(bind(&ObsGame::UpdateBad, DaJi));

  LaoBan->Notify();
}

15. 抽象工厂模式

  • 提供一个接口, 创建相关/依赖对象的家族, 无需明确指定具体类
  • 优点: 一系列相关产品进行组合, 客户端无需关心具体工厂和产品, 降低客户端与具体实现的耦合
  • 缺点: 难以支持新种类产品
  • 没看完

在这里插入图片描述


16.状态模式

  • 当一个对象内在状态改变时允许改变其行为, 看起来像改变了其类
  • 当一个对象行为取决于其状态, 且必须在运行时刻根据状态改变行为时使用
  • 优点: 将特定状态相关的行为局部化, 将不同状态的行为分隔开

在这里插入图片描述

#include <iostream>

class State;

class Work {
private:
    State* current;
public:
    Work();
    double Hour;
    bool TaskFinished;
    void SetState(State* s);
    void WriteProgram();
};

class State {
public:
    virtual void WriteProgram(Work* w) = 0;
};

class ForenoonState : public State {
public:
    void WriteProgram(Work* w) override;
};

class NoonState : public State {
public:
    void WriteProgram(Work* w) override;
};

class AfternoonState : public State {
public:
    void WriteProgram(Work* w) override;
};

class EveningState : public State {
public:
    void WriteProgram(Work* w) override;
};

class SleepingState : public State {
public:
    void WriteProgram(Work* w) override;
};

class RestState : public State {
public:
    void WriteProgram(Work* w) override;
};

// Work 类的构造函数
Work::Work() {
    current = new ForenoonState();
}

void Work::SetState(State* s) {
    current = s;
}

void Work::WriteProgram() {
    current->WriteProgram(this);
}

void ForenoonState::WriteProgram(Work* w) {
    if (w->Hour < 12) {
        std::cout << "当前时间:" << w->Hour << "点 上午工作,精神百倍" << std::endl;
    } else {
        w->SetState(new NoonState());
        w->WriteProgram();
    }
}

void NoonState::WriteProgram(Work* w) {
    if (w->Hour < 13) {
        std::cout << "当前时间:" << w->Hour << "点 饿了,午饭;犯困,午休。" << std::endl;
    } else {
        w->SetState(new AfternoonState());
        w->WriteProgram();
    }
}

void AfternoonState::WriteProgram(Work* w) {
    if (w->Hour < 17) {
        std::cout << "当前时间:" << w->Hour << "点 下午状态还不错,继续努力" << std::endl;
    } else {
        w->SetState(new EveningState());
        w->WriteProgram();
    }
}

void EveningState::WriteProgram(Work* w) {
    if (w->TaskFinished) {
        w->SetState(new RestState());
        w->WriteProgram();
    } else {
        if (w->Hour < 21) {
            std::cout << "当前时间:" << w->Hour << "点 加班哦,疲累之极" << std::endl;
        } else {
            w->SetState(new SleepingState());
            w->WriteProgram();
        }
    }
}

void SleepingState::WriteProgram(Work* w) {
    std::cout << "当前时间:" << w->Hour << "点 不行了,睡着了。" << std::endl;
}

void RestState::WriteProgram(Work* w) {
    std::cout << "当前时间:" << w->Hour << "点 下班回家了" << std::endl;
}

int main() {
    // 紧急项目
    Work emergencyProjects;
    emergencyProjects.Hour = 9;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 10;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 12;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 13;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 14;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 17;

    // emergencyProjects.WorkFinished = true;
    emergencyProjects.TaskFinished = false;

    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 19;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 22;
    emergencyProjects.WriteProgram();

    return 0;
}

17.适配器模式

  • 将一个类的接口转换为客户希望的另一个接口, 解决接口兼容问题

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;

class Epeople {
protected:
  string Name;
public:
  Epeople(string name) : Name(name) {}
  virtual void speak() = 0;
};

class Chinese{
protected:
  string Ming;
public:
  Chinese(string ming) : Ming(ming) {}
  void shuo() {
    cout << "朕是 " << Ming << endl;
  }
};

class American : public Epeople {
public:
  American(string name) : Epeople(name) {}
  void speak() {
    cout << "I am " << Name << endl;
  }
};

class Translator : public Epeople {
  Chinese* zhong = new Chinese(Name);
public:
  Translator(string name) : Epeople(name) {}
  void speak() {
    zhong->shuo();
  }
};

int main() {
  American jack("Musk");
  Translator fanyi("嬴政");
  jack.speak();
  fanyi.speak();

  return 0;
}

18.备忘录模式

  • 不破坏封装性前提下, 捕获一个对象内部状态, 在该对象外保存状态
  • 适用于功能复杂但要维护/记录属性历史的类 / 保存属性只是众多属性小部分

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;
class StateMemento{
public:
  int state1;
  int state2;
  int state3;
  StateMemento(int s1,int s2, int s3){
    this->state1 = s1;
    this->state2 = s2;
    this->state3 = s3;
  }
};

class APP{
  int state1;
  int state2;
  int state3;
public:
  APP(int s1, int s2, int s3):state1(s1),state2(s2),state3(s3){}
  void setState(int s1, int s2, int s3){
    this->state1 = s1;
    this->state2 = s2;
    this->state3 = s3;
  }
  void stateDis(){
    cout << "state:" << state1 << " " << state2 << " " << state3 << endl;
  }
  StateMemento* save(){
    return (new StateMemento(state1, state2, state3));
  }
  void RecoveryState(StateMemento* memento){
    this->state1 = memento->state1;
    this->state2 = memento->state2;
    this->state3 = memento->state3;
  }
};

class StateMan{
public:
  StateMemento* memento;
  StateMan(){}
};

int main(){
  APP app(1,2,3);
  app.stateDis();

  StateMan* man = new StateMan();
  man->memento = app.save();

  app.setState(4,5,6);
  app.stateDis();
  
  app.RecoveryState(man->memento);
  app.stateDis();
}

19.组合模式

  • 将对象组合成树形结构表示部分-整体的层次结构, 用户对单个对象和组合对象的使用有一致性

在这里插入图片描述

#include<iostream>
#include<string>
#include<vector>
using namespace std;

class Company{
protected:
public:
  string _name;
  Company(string name):_name(name){}
  virtual void add(Company *c) = 0;
  virtual void remove(Company *c) = 0;
  virtual void display(int depth) = 0;
  virtual void lineOfDuty() = 0;
};

class ConcreteCompany:public Company{
private:
  vector<Company*>* _children;
public:
  ConcreteCompany(string name):Company(name){
    _children = new vector<Company*>();
  }
  void add(Company *c){
    _children->push_back(c);
  }
  void remove(Company *c){
    for(auto it = _children->begin(); it != _children->end(); it++){
      if((*it)->_name == c->_name){
        _children->erase(it);
        break;
      }
    }
  }
  void display(int depth){
    for(int i = 0; i < depth; i++){
      cout << "-";
    }
    cout << _name << endl;
    for(auto it = _children->begin(); it != _children->end(); it++){
      (*it)->display(depth + 2);
    }
  }
  void lineOfDuty(){
    for(auto it = _children->begin(); it != _children->end(); it++){
      (*it)->lineOfDuty();
    }
  }
};

class HRDepartment:public Company{
public:
  HRDepartment(string name):Company(name){}
  void add(Company *c){}
  void remove(Company *c){}
  void display(int depth){
    for(int i = 0; i < depth; i++){
      cout << "-";
    }
    cout << _name << endl;
  }
  void lineOfDuty(){
    cout << _name << "员工招聘培训管理" << endl;
  }
};

class FinanceDepartment:public Company{
public:
  FinanceDepartment(string name):Company(name){}
  void add(Company *c){}
  void remove(Company *c){}
  void display(int depth){
    for(int i = 0; i < depth; i++){
      cout << "-";
    }
    cout << _name << endl;
  }
  void lineOfDuty(){
    cout << _name << "公司财务收支管理" << endl;
  }
};

int main(){
  system("chcp 65001\n"); // Execute command line command chcp 65001

  ConcreteCompany *root = new ConcreteCompany("北京总公司");
  root->add(new HRDepartment("总公司人力资源部"));
  root->add(new FinanceDepartment("总公司财务部"));

  ConcreteCompany *comp = new ConcreteCompany("上海华东分公司");
  comp->add(new HRDepartment("华东分公司人力资源部"));
  comp->add(new FinanceDepartment("华东分公司财务部"));
  root->add(comp);

  ConcreteCompany *comp1 = new ConcreteCompany("南京办事处");
  comp1->add(new HRDepartment("南京办事处人力资源部"));
  comp1->add(new FinanceDepartment("南京办事处财务部"));
  comp->add(comp1);

  ConcreteCompany *comp2 = new ConcreteCompany("杭州办事处");
  comp2->add(new HRDepartment("杭州办事处人力资源部"));
  comp2->add(new FinanceDepartment("杭州办事处财务部"));
  comp->add(comp2);

  cout << "结构图:" << endl;
  root->display(1);

  cout << "职责:" << endl;
  root->lineOfDuty();

  return 0;
}

20.迭代器模式

  • 提供一种方法顺序访问一个聚合对象的各个元素, 不暴露对象的内部表示

在这里插入图片描述

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Iterator {
public:
  virtual void First() = 0;
  virtual void Next() = 0;
  virtual bool IsDone() = 0;
  virtual string CurrentItem() = 0;
};

class Aggregate {
public:
  virtual Iterator* CreateIterator() = 0;
};

class ConcreteAggregate : public Aggregate {
private:
  vector<string> m_vecItems;
public:
  Iterator* CreateIterator();

  int Count() {
    return m_vecItems.size();
  }

  string GetItem(int idx) {
    return m_vecItems[idx];
  }

  void SetItem(int idx, string str) {
    m_vecItems[idx] = str;
  }

  void PushItem(string str) {
    m_vecItems.push_back(str);
  }
};

class ConcreteIterator : public Iterator {
private:
  ConcreteAggregate* m_pAggregate;
  int current = 0;

public:
  ConcreteIterator(ConcreteAggregate* pAggregate) {
    m_pAggregate = pAggregate;
  }

  void First() override {
    current = 0;
  }

  void Next() override {
    if (current < m_pAggregate->Count())
      current++;
  }

  bool IsDone() override {
    return current >= m_pAggregate->Count();
  }

  string CurrentItem() override {
    return m_pAggregate->GetItem(current);
  }
};

Iterator* ConcreteAggregate::CreateIterator() {
    return new ConcreteIterator(this);
}

int main()
{
  ConcreteAggregate* pAggregate = new ConcreteAggregate();
  pAggregate->PushItem("A");
  pAggregate->PushItem("B");
  pAggregate->PushItem("C");
  pAggregate->PushItem("D");
  pAggregate->PushItem("E");

  Iterator* pIterator = pAggregate->CreateIterator();
  for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
  {
    cout << pIterator->CurrentItem() << endl;
  }

  delete pAggregate;
  delete pIterator;

  cout << " ConcreteAggregate:" << sizeof(ConcreteAggregate) << " ConcreteIterator:" << sizeof(ConcreteIterator) << endl;

  return 0;
}

21.单例模式

  • 保证一个类仅有一个实例, 提供一个访问它的全局访问点. 构造方法私有化
#include<iostream>
#include<string>

using namespace std;

class Singleton {
private:
  static Singleton* instance;
  Singleton() {}
public:
  static Singleton* GetInstance() {
    if (instance == nullptr) {
      instance = new Singleton();
      cout << "instance created" << endl;
    } else {
      cout << "instance already exists" << endl;
    }
    return instance;
  }
  static void DeleteInstance() {
    delete instance;
    instance = nullptr;
    cout << "instance deleted" << endl;
  }
};
Singleton* Singleton::instance = nullptr;
int main() {
  Singleton* s1 = Singleton::GetInstance();
  s1->DeleteInstance();
  Singleton* s2 = Singleton::GetInstance();

  return 0;
}

22.桥接模式

  • 将抽象部分与其实现部分分离, 使其都可以独立变化(实现系统可能有多角度分类, 每种分类都可能变化, 将这种多角度分离让其独立变化, 减少耦合)
    合成/聚合复用原则: 尽量用合成/聚合,尽量不用继承
  • 优点: 助于每个类被封装, 集中在单个任务上, 类和类层次会保持较小规模, 不会过度增长

在这里插入图片描述

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class HandsetSoft {
public:
  virtual void Run() = 0;
};

class HandsetGame : public HandsetSoft {
public:
  void Run() override {
    cout << "Run game" << endl;
  }
};

class HandsetAddressList : public HandsetSoft {
public:
  void Run() override {
    cout << "Run address list" << endl;
  }
};

class HandsetBrand {
protected:
  HandsetSoft* soft;
public:
  void SetHandsetSoft(HandsetSoft* soft) {
    this->soft = soft;
  }
  virtual void Run() = 0;
};

class HandsetBrandN : public HandsetBrand {
public:
  void Run() override {
    soft->Run();
  }
};

class HandsetBrandM : public HandsetBrand {
public:
  void Run() override {
    soft->Run();
  }
};

int main(){
  HandsetBrand* ab = new HandsetBrandN();
  ab->SetHandsetSoft(new HandsetGame());
  ab->SetHandsetSoft(new HandsetAddressList());
  ab->Run();

  return 0;
}

23.命令模式

  • 将一个请求封装为一个对象, 从而使可用不同请求对客户进行参数化: 对请求排队/请求日志/支持可撤销的操作
  • 优点: 分离请求操作的对象与执行操作的对象
    • 容易设计命令队列
    • 容易记入日志
    • 允许接受请求一方决定是否否决请求
    • 容易实现请求撤销和重做
    • 容易新增具体命令类

在这里插入图片描述

#include<iostream>
#include<string>

using namespace std;

class Barbecuer {
public:
  void BakeMutton() {
    cout << "Bake mutton" << endl;
  }
  void BakeChickenWing() {
    cout << "Bake chicken wing" << endl;
  }
};

class Command {
protected:
  Barbecuer* receiver;
  Command(Barbecuer* receiver) {
    this->receiver = receiver;
  }
public:
  virtual void ExecuteCommand() = 0;
};

class BakeMuttonCommand : public Command {
public:
  BakeMuttonCommand(Barbecuer* receiver) : Command(receiver) {}
  void ExecuteCommand() override {
    receiver->BakeMutton();
  }
};

class BakeChickenWingCommand : public Command {
public:
  BakeChickenWingCommand(Barbecuer* receiver) : Command(receiver) {}
  void ExecuteCommand() override {
    receiver->BakeChickenWing();
  }
};

class Waiter {
private:
  Command* command;
public:
  void SetCommand(Command* command) {
    this->command = command;
  }
  void Notify() {
    command->ExecuteCommand();
  }
};

int main() {
  Barbecuer* boy = new Barbecuer();
  Command* bakeMuttonCommand1 = new BakeMuttonCommand(boy);
  Command* bakeMuttonCommand2 = new BakeMuttonCommand(boy);
  Command* bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
  Waiter* girl = new Waiter();

  girl->SetCommand(bakeMuttonCommand1);
  girl->Notify();
  girl->SetCommand(bakeMuttonCommand2);
  girl->Notify();
  girl->SetCommand(bakeChickenWingCommand1);
  girl->Notify();
  return 0;
}

24.职责链模式

  • 使多个对象都有机会处理请求, 避免请求的发送者和接收者的耦合关系. 将该对象连成一条链, 沿该链传递请求, 直到有对象处理它
  • 优点:
    • 接收者和发送者都没有对方的明确信息, 链中对象不清楚链的结构, 简化对象的相互连接, 降低耦合

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class Request{
public:
  string requestType;
  string requestContent;
  int number;
};

class Manager{
protected:
  string _name;
  Manager* _superior;
public:
  Manager(string name):_name(name){}
  void SetSuperior(Manager* superior){
    _superior = superior;
  }
  virtual void RequestApplications(Request* request) = 0;
};

class CommonManager:public Manager{
public:
  CommonManager(string name):Manager(name){}
  void RequestApplications(Request* request){
    if(request->requestType == "请假" && request->number <= 2) {
      cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
    } else {
      if(_superior != NULL) {
        _superior->RequestApplications(request);
      }
    }
  }
};

class Majordomo:public Manager{
public:
  Majordomo(string name):Manager(name){}
  void RequestApplications(Request* request){
    if(request->requestType == "请假" && request->number <= 5) {
      cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
    } else {
      if(_superior != NULL) {
        _superior->RequestApplications(request);
      }
    }
  }
};

class GeneralManager:public Manager{
public:
  GeneralManager(string name):Manager(name){}
  void RequestApplications(Request* request){
    if(request->requestType == "请假" && request->number <= 5) {
      cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
    } else if(request->requestType == "加薪" && request->number <= 500) {
      cout << _name << ":" << request->requestContent << "数量" << request->number << "被批准" << endl;
    } else if(request->requestType == "加薪" && request->number > 500) {
      cout << _name << ":" << request->requestContent << "数量" << request->number << "再说吧" << endl;
    }
  }
};

int main()
{
  system("chcp 65001\n"); // Execute command line command chcp 65001
  
  Manager* common = new CommonManager("经理");
  Manager* majordomo = new Majordomo("总监");
  Manager* general = new GeneralManager("总经理");
  common->SetSuperior(majordomo);
  majordomo->SetSuperior(general);

  Request* request = new Request();
  request->requestType = "请假";
  request->requestContent = "小菜请假";
  request->number = 1;
  common->RequestApplications(request);

  request->requestType = "请假";
  request->requestContent = "小菜请假";
  request->number = 4;
  common->RequestApplications(request);

  request->requestType = "加薪";
  request->requestContent = "小菜请求加薪";
  request->number = 500;
  common->RequestApplications(request);

  request->requestType = "加薪";
  request->requestContent = "小菜请求加薪";
  request->number = 1000;
  common->RequestApplications(request);

  return 0;
}

25.中介者模式 Mediator

  • (调停者模式) 用一个中介对象来封装一系列的对象交互, 让对象无需显式相互引用, 耦合松散, 可独立改变其之间交互
  • 通常应用于一组对象以定义良好但复杂的方式进行通信的场合
  • 优点:
    • 容易在系统中应用
  • 缺点:
    • 中介类最复杂
      在这里插入图片描述
#include<iostream>
#include<string>
using namespace std;

class UniteNations;

class Country {
protected:
  UniteNations* _mediator;
public:
  Country(UniteNations* mediator):_mediator(mediator){}
};

class UniteNations {
public:
  virtual void Declare(string message, Country* country) = 0;
};

class USA:public Country {
public:
  USA(UniteNations* mediator):Country(mediator){}
  void Declare(string message){
    _mediator->Declare(message, this);
  }
  void GetMessage(string message){
    cout << "USA获得对方信息:" << message << endl;
  }
};

class Iraq:public Country {
public:
  Iraq(UniteNations* mediator):Country(mediator){}
  void Declare(string message){
    _mediator->Declare(message, this);
  }
  void GetMessage(string message){
    cout << "Iraq获得对方信息:" << message << endl;
  }
};

class UniteNationsSecurityCouncil:public UniteNations {
private:
  USA* _usa;
  Iraq* _iraq;
public:
  void SetUSA(USA* usa){
    _usa = usa;
  }
  void SetIraq(Iraq* iraq){
    _iraq = iraq;
  }
  void Declare(string message, Country* country){
    if(country == _usa){
      _iraq->GetMessage(message);
    } else if(country == _iraq){
      _usa->GetMessage(message);
    }
  }
};

int main () {
  system("chcp 65001\n"); // Execute command line command chcp 65001
  UniteNationsSecurityCouncil* UNSC = new UniteNationsSecurityCouncil();
  USA* usa = new USA(UNSC);
  Iraq* iraq = new Iraq(UNSC);
  UNSC->SetUSA(usa);
  UNSC->SetIraq(iraq);
  usa->Declare("不准研制核武器,否则要发动战争!");
  iraq->Declare("我们没有核武器,也不怕侵略。");
  return 0;
}

26.享元模式 Flyweight

  • 用共享技术有效支持大量细粒度对象, 避免大量类似的开销
    • 在程序设计中, 有时需要生成大量细粒度的类实例表示数据, 如果能发现这些实例除了几个参数外基本相同, 则将不同的参数移到类实例的外面, 在方法调用时传递进来, 就可以通过共享大幅度减少单个实例的数目
  • 内部状态: 在享元对象内部且不随环境改变而改变的共享部分
  • 外部状态: 随环境改变而改变的, 不可以共享的状态
  • 使用场景:
    • 若一个应用使用了大量对象, 这些对象造成了很大的内存开销时考虑使用;
    • 对象大多数状态可以外部状态, 删除外部状态可用较少的共享对象取代多组对象

在这里插入图片描述

#include<iostream>
#include<string>
#include<map>
using namespace std;


class User {
private:
  string _name;
public:
  User(string name):_name(name){}
  string GetName(){
    return _name;
  }
};

class Website {
public:
  virtual void Use(User* user) = 0;
};

class ConcreteWebsite:public Website {
private:
  string _name;
public:
  ConcreteWebsite(string name):_name(name){}
  void Use(User* user){
    cout << " 网站分类:" << _name << " 用户: " << user->GetName() << endl;
  }
};

class WebsiteFactory {
private:
  map<string, Website*> _flyweights;
public:
  Website* GetWebsiteCategory(string key){
    if(_flyweights.find(key) == _flyweights.end()){
      _flyweights[key] = new ConcreteWebsite(key);
    }
    return _flyweights[key];
  }
  int GetWebsiteCount(){
    return _flyweights.size();
  }
};


int main(){
  WebsiteFactory*f = new WebsiteFactory();
  Website* fx = f->GetWebsiteCategory("项目经历");
  fx->Use(new User("ToBuildAnArmy"));
  Website* fy = f->GetWebsiteCategory("项目经历");
  fy->Use(new User("玉竹笑"));
  Website* fz = f->GetWebsiteCategory("产品展示");
  fz->Use(new User("AcE&ArMs"));
  Website* f1 = f->GetWebsiteCategory("404 error");
  f1->Use(new User("404 error"));

  cout << "网站分类总数为:" << f->GetWebsiteCount() << endl;

  return 0;
}

27.解释器模式 interpreter

  • 给定一个语言, 定义其文法的一种表示, 定义一个解释器, 使用该表示来解释语言中的句子
    • 当一个语言需要解释执行, 该语言的句子可表示为一个抽象语法树
  • 特点: 容易改变和扩展文法,
  • 缺点: 为文法的每一条规则至少定义一个类, 包含多规则的文法可能难以管理维护

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class PlayContext {
private:
  string _text;
public:
  string GetText(){
    return _text;
  }
  void SetText(string text){
    _text = text;
  }
};

class Expression {
public:
  virtual void Interpret(PlayContext* context) = 0;
  virtual void Excute(string key, double value) = 0;
};

class Note:public Expression {
public:
  void Interpret(PlayContext* context){
    string playKey = context->GetText().substr(0, 1);
    // context->SetText(context->GetText().substr(2));
    string text = context->GetText();
    if (text.length() > 2) {
      context->SetText(context->GetText().substr(2));
    } else {
        // Handle error
        return;
    }
    double playValue = stod(context->GetText().substr(0, context->GetText().find(" ")));
    context->SetText(context->GetText().substr(context->GetText().find(" ") + 1));
    Excute(playKey, playValue);
  }
  void Excute(string key, double value){
    string note;
    if(key == "C"){
      note = "1";
    } else if(key == "D"){
      note = "2";
    } else if(key == "E"){
      note = "3";
    } else if(key == "F"){
      note = "4";
    } else if(key == "G"){
      note = "5";
    } else if(key == "A"){
      note = "6";
    } else if(key == "B"){
      note = "7";
    }
    cout << note << " ";
  }
};

class Scale:public Expression {
public:
  void Interpret(PlayContext* context){
    string playKey = context->GetText().substr(0, 1);
    // context->SetText(context->GetText().substr(2));
    string text = context->GetText();
    if (text.length() > 2) {
      context->SetText(context->GetText().substr(2));
    } else {
        // Handle error
        return;
    }
    double playValue = stod(context->GetText().substr(0, context->GetText().find(" ")));
    context->SetText(context->GetText().substr(context->GetText().find(" ") + 1));
    Excute(playKey, playValue);
  }
  void Excute(string key, double value){
    string scale;
    switch((int)value){
      case 1:
        scale = "低音";
        break;
      case 2:
        scale = "中音";
        break;
      case 3:
        scale = "高音";
        break;
    }
  }
};

int main() {
  PlayContext* context = new PlayContext();
  cout << "上海滩:";
  context->SetText("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 3");
  Expression* expression = NULL;
  while(context->GetText().length() > 0){
    string str = context->GetText().substr(0, 1);
    if(str == "O"){
      expression = new Scale();
    } else {
      expression = new Note();
    }
    expression->Interpret(context);
  }
  return 0;
}

28.访问者模式 Visitor

  • 表示一个作用于某对象结构中的各元素的操作, 可在不改变各元素的类的前提下定义作用于这些元素的新操作
  • 作用: 目的要把处理从数据结构分离, 使算法操作的增加变得容易

在这里插入图片描述

#include<iostream>
#include<string>
using namespace std;

class Man;
class Woman;

class Action {
public:
  virtual void GetManConclusion() = 0;
  virtual void GetWomanConclusion() = 0;
};

class Person {
public:
  virtual void Accept(Action* visitor) = 0;
};

class Success:public Action {
public:
  void GetManConclusion(){
    cout << "男人成功时,背后多半有一个伟大的女人。" << endl;
  }
  void GetWomanConclusion(){
    cout << "女人成功时,背后多半有一个不成功的男人。" << endl;
  }
};

class Failing:public Action {
public:
  void GetManConclusion(){
    cout << "男人失败时,闷头喝酒,谁也不用劝。" << endl;
  }
  void GetWomanConclusion(){
    cout << "女人失败时,眼泪汪汪,谁也劝不了。" << endl;
  }
};

class Man:public Person {
public:
  void Accept(Action* visitor){
    visitor->GetManConclusion();
  }
};

class Woman:public Person {
public:
  void Accept(Action* visitor){
    visitor->GetWomanConclusion();
  }
};

class ObjectStructure {
private:
  Person* _elements[100];
  int _size;
public:
  void Attach(Person* element){
    _elements[_size++] = element;
  }
  void Detach(Person* element){
    // ...
  }
  void Display(Action* visitor){
    for(int i = 0; i < _size; i++){
      _elements[i]->Accept(visitor);
    }
  }
};

int main(){
  ObjectStructure *o = new ObjectStructure();
  o->Attach(new Man());
  o->Attach(new Woman());

  Success* v1 = new Success();
  o->Display(v1);

  Failing* v2 = new Failing();
  o->Display(v2);
}
  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值