当前位置: 首页 > news >正文

基于C++的《Head First设计模式》笔记——模式合作

目录

一.专栏简介

二.模式合作

三.与鸭子重聚

1.创建一个Quackable接口

2.鸭子实现Quackable

3.模拟器

四.加上鹅

五.鹅适配器

六.模拟器中加入鹅

七.叫声的统计

八.模拟器加入装饰者

九.工厂生产鸭子

十.模拟器使用工厂

十一.创建一群鸭子

十二.修改模拟器

十三.加入观察者模式代码

十四.总结


一.专栏简介

本专栏是我学习《head first》设计模式的笔记。这本书中是用Java语言为基础的,我将用C++语言重写一遍,并且详细讲述其中的设计模式,涉及是什么,为什么,怎么做,自己的心得等等。希望阅读者在读完我的这个专题后,也能在开发中灵活且正确的使用,或者在面对面试官时,能够自信地说自己熟悉常用设计模式。

本章将开始模式合作的学习,这是复合模式的前传。

二.模式合作

模式通常被一起使用,并结合在同一个设计解决方案中。

复合模式在一个解决方案中结合两个或多个模式,以解决一般的或重复发生的问题。

三.与鸭子重聚

正如你已经知道的,我们会再次和鸭子合作,这一次,鸭子将在同一个解决方案中,展示模式如何共存甚至合作。

我们将从头重建我们的鸭子模拟器,并通过使用一堆模式,给它一些有趣的能力,OK,我们开始......

1.创建一个Quackable接口

struct Quackable { virtual void quack() = 0; };

2.鸭子实现Quackable

class MallardDuck : public Quackable { public: void quack() override { cout << "Quack" << endl; } }; class RedheadDuck : public Quackable { public: void quack() override { cout << "Quack" << endl; } }; // 鸭鸣器 class DuckCall : public Quackable { public: void quack() override { cout << "Kwak" << endl; } }; // 橡皮鸭 class RubberDuck : public Quackable { public: void quack() override { cout << "Squeak" << endl; } };

3.模拟器

我们制造一个模拟器,这个模拟器会创建一些鸭子,并保证它们会呱呱叫......

static void simulate(Quackable* duck) { duck->quack(); } static void simulate() { Quackable* mallardDuck = new MallardDuck(); Quackable* redheadDuck = new RedheadDuck(); Quackable* duckCall = new DuckCall(); Quackable* rubberDuck = new RubberDuck(); cout << "Duck Simulator\n"; simulate(mallardDuck); simulate(redheadDuck); simulate(duckCall); simulate(rubberDuck); } int main() { simulate(); return 0; }

运行结果:

四.加上鹅

class Goose { public: void honk() { cout << "Honk" << endl; } };

假设我们想要在使用鸭的地方使用鹅,毕竟鹅也会叫、会飞、会游。为什么我们不能在模拟器中使用鹅?适配器模式可以让我们轻易地将鸭和鹅掺和在一起。

五.鹅适配器

class GooseAdapter : public Quackable { public: GooseAdapter(Goose* g): goose(g) {} void quack() override { goose->honk(); } private: Goose* goose; };

六.模拟器中加入鹅

static void simulate(Quackable* duck) { duck->quack(); } static void simulate() { Quackable* mallardDuck = new MallardDuck(); Quackable* redheadDuck = new RedheadDuck(); Quackable* duckCall = new DuckCall(); Quackable* rubberDuck = new RubberDuck(); Quackable* gooseDuck = new GooseAdapter(new Goose()); cout << "Duck Simulator\n"; simulate(mallardDuck); simulate(redheadDuck); simulate(duckCall); simulate(rubberDuck); simulate(gooseDuck); } int main() { simulate(); return 0; }

运行结果:

呱呱叫学家为可呱呱叫行为的所有方面着迷,方法学家经常研究的其中一件事:在一群鸭子中,总共发出了多少呱呱叫声?

在不必修改鸭子类的情况下,我们如何添加统计嘎嘎叫次数的能力,当然是装饰模式为鸭子类加上统计嘎嘎叫的责任和能力。

七.叫声的统计

class QuackCounter : public Quackable { public: QuackCounter(Quackable* d): duck(d) {} void quack() { duck->quack(); ++numberOfQuacks; } static int getQuacks() { return numberOfQuacks; } private: Quackable* duck; static int numberOfQuacks; };

八.模拟器加入装饰者

#include "compound.h" static void simulate(Quackable* duck) { duck->quack(); } static void simulate() { Quackable* mallardDuck = new QuackCounter(new MallardDuck()); Quackable* redheadDuck = new QuackCounter(new RedheadDuck()); Quackable* duckCall = new QuackCounter(new DuckCall()); Quackable* rubberDuck = new QuackCounter(new RubberDuck()); Quackable* gooseDuck = new GooseAdapter(new Goose()); cout << "Duck Simulator\n"; simulate(mallardDuck); simulate(redheadDuck); simulate(duckCall); simulate(rubberDuck); simulate(gooseDuck); cout << "The ducks quacked " << QuackCounter::getQuacks() << " times" << endl; } int main() { simulate(); return 0; }

运行结果:

但是这有问题:我们不得不确认它们被包装,否则就得不到被装饰的行为。

我们需要封装鸭子的创建和装饰,这就是工厂模式。

九.工厂生产鸭子

我们需要一些质量控制,以确保鸭子得到包装。我们建造一个完整的工厂,专门生产这些鸭子。该工厂应该生产产品家族,包含不同类型的鸭子,因此我们要用抽象工厂模式。

class AbstractDuckFactory { public: virtual Quackable* createMallardDuck() = 0; virtual Quackable* createRedheadDuck() = 0; virtual Quackable* createDuckCall() = 0; virtual Quackable* createRubberDuck() = 0; }; class DuckFactory : public AbstractDuckFactory { public: Quackable* createMallardDuck() override { return new MallardDuck(); } Quackable* createRedheadDuck() override { return new RedheadDuck(); } Quackable* createDuckCall() override { return new DuckCall(); } Quackable* createRubberDuck() override { return new RubberDuck(); } }; class CountingDuckFactory : public AbstractDuckFactory { public: Quackable* createMallardDuck() override { return new QuackCounter(new MallardDuck()); } Quackable* createRedheadDuck() override { return new QuackCounter(new RedheadDuck()); } Quackable* createDuckCall() override { return new QuackCounter(new DuckCall()); } Quackable* createRubberDuck() override { return new QuackCounter(new RubberDuck()); } };

其中一个创建不带装饰者鸭子的工厂和一个带装饰者鸭子的工厂。

十.模拟器使用工厂

static void simulate(Quackable* duck) { duck->quack(); } static void simulate(AbstractDuckFactory* duckFactory) { Quackable* mallardDuck = duckFactory->createMallardDuck(); Quackable* redheadDuck = duckFactory->createRedheadDuck(); Quackable* duckCall = duckFactory->createDuckCall(); Quackable* rubberDuck = duckFactory->createRubberDuck(); Quackable* gooseDuck = new GooseAdapter(new Goose()); cout << "Duck Simulator\n"; simulate(mallardDuck); simulate(redheadDuck); simulate(duckCall); simulate(rubberDuck); simulate(gooseDuck); cout << "The ducks quacked " << QuackCounter::getQuacks() << " times" << endl; } int main() { AbstractDuckFactory* duckFactory = new CountingDuckFactory(); simulate(duckFactory); return 0; }

运行结果:

和上次一样,但是这次我们确定所有的鸭子都被装饰过,因为我们使用了CountingDuckFactory。

但现在的问题是要分别管理这些不同的鸭子变得有些困难了,我们想把这些鸭子作为一个整体来管理,甚至让我们能够管理几个想持续追踪的鸭子家族。

我们需要一种方法来谈论鸭子集合,甚至子集合。这显然是组合模式。

十一.创建一群鸭子

组合模式允许我们将一个对象集合像单个对象一样对待,对一群Quackable来说,组合模式最合适不过了!

让我们逐步看如何运作:

class Flock : public Quackable { public: void add(Quackable* quackable) { quackers.push_back(quackable); } void quack() { for (const auto& e : quackers) { e->quack(); } } private: vector<Quackable*> quackers; };

这里我们还用到了迭代器模式,也就是quack里的那个语法糖循环。

十二.修改模拟器

#include "compound.h" static void simulate(Quackable* duck) { duck->quack(); } static void simulate(AbstractDuckFactory* duckFactory) { Quackable* redheadDuck = duckFactory->createRedheadDuck(); Quackable* duckCall = duckFactory->createDuckCall(); Quackable* rubberDuck = duckFactory->createRubberDuck(); Quackable* gooseDuck = duckFactory->createGooseDuck(); Flock* flockOfDucks = new Flock(); flockOfDucks->add(redheadDuck); flockOfDucks->add(duckCall); flockOfDucks->add(rubberDuck); flockOfDucks->add(gooseDuck); Flock* flockOfMallard = new Flock(); Quackable* mallard1 = duckFactory->createMallardDuck(); Quackable* mallard2 = duckFactory->createMallardDuck(); Quackable* mallard3 = duckFactory->createMallardDuck(); Quackable* mallard4 = duckFactory->createMallardDuck(); flockOfMallard->add(mallard1); flockOfMallard->add(mallard2); flockOfMallard->add(mallard3); flockOfMallard->add(mallard4); flockOfDucks->add(flockOfMallard); cout << "Duck Simulator : Whole Flock Simulation\n"; simulate(flockOfDucks); cout << "\nDuck Simulator : Mallard Flock Simulation\n"; simulate(flockOfMallard); cout << "The ducks quacked " << QuackCounter::getQuacks() << " times" << endl; } int main() { AbstractDuckFactory* duckFactory = new CountingDuckFactory(); simulate(duckFactory); return 0; }

运行结果:

组合运行得很流畅!但现在我们有一个相反的要求:我们还需要跟踪个别的鸭子,支持我们跟踪个别鸭子的实时嘎嘎叫。观察者模式上场。

十三.加入观察者模式代码

compound.h:

#pragma once #include <iostream> #include <vector> using namespace std; class Observer; struct QuackObservable { virtual void registerObservable(Observer* observer) = 0; virtual void notifyObservers() = 0; }; class Observer { public: virtual void update(QuackObservable* duck) = 0; }; class QuackoLogist : public Observer { public: void update(QuackObservable* duck) override { cout << "QuackoLogist:" << typeid(*duck).name() << " just quacked." << endl; } }; struct Quackable : public QuackObservable { virtual void quack() = 0; }; class Observable : public QuackObservable { public: Observable(QuackObservable* d): duck(d) {} void registerObservable(Observer* observer) override { observers.push_back(observer); } void notifyObservers() override { for (const auto& e : observers) { e->update(duck); } } private: vector<Observer*> observers; QuackObservable* duck; }; class MallardDuck : public Quackable { public: MallardDuck() { observable = new Observable(this); } void quack() override { cout << "Quack" << endl; notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } private: Observable* observable; }; class RedheadDuck : public Quackable { public: RedheadDuck() { observable = new Observable(this); } void quack() override { cout << "Quack" << endl; notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } private: Observable* observable; }; // 鸭鸣器 class DuckCall : public Quackable { public: DuckCall() { observable = new Observable(this); } void quack() override { cout << "Kwak" << endl; notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } private: Observable* observable; }; // 橡皮鸭 class RubberDuck : public Quackable { public: RubberDuck() { observable = new Observable(this); } void quack() override { cout << "Squeak" << endl; notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } private: Observable* observable; }; class Goose { public: void honk() { cout << "Honk" << endl; } }; class GooseAdapter : public Quackable { public: GooseAdapter(Goose* g): goose(g) { observable = new Observable(this); } void quack() override { goose->honk(); notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } private: Goose* goose; Observable* observable; }; class QuackCounter : public Quackable { public: QuackCounter(Quackable* d): duck(d) { observable = new Observable(this); } void quack() { duck->quack(); ++numberOfQuacks; notifyObservers(); } void registerObservable(Observer* observer) override { observable->registerObservable(observer); } void notifyObservers() override { observable->notifyObservers(); } static int getQuacks() { return numberOfQuacks; } private: Quackable* duck; static int numberOfQuacks; Observable* observable; }; int QuackCounter::numberOfQuacks; class AbstractDuckFactory { public: virtual Quackable* createMallardDuck() = 0; virtual Quackable* createRedheadDuck() = 0; virtual Quackable* createDuckCall() = 0; virtual Quackable* createRubberDuck() = 0; virtual Quackable* createGooseDuck() = 0; }; class DuckFactory : public AbstractDuckFactory { public: Quackable* createMallardDuck() override { return new MallardDuck(); } Quackable* createRedheadDuck() override { return new RedheadDuck(); } Quackable* createDuckCall() override { return new DuckCall(); } Quackable* createRubberDuck() override { return new RubberDuck(); } Quackable* createGooseDuck() override { return new GooseAdapter(new Goose()); } }; class CountingDuckFactory : public AbstractDuckFactory { public: Quackable* createMallardDuck() override { return new QuackCounter(new MallardDuck()); } Quackable* createRedheadDuck() override { return new QuackCounter(new RedheadDuck()); } Quackable* createDuckCall() override { return new QuackCounter(new DuckCall()); } Quackable* createRubberDuck() override { return new QuackCounter(new RubberDuck()); } Quackable* createGooseDuck() override { return new GooseAdapter(new Goose()); } }; class Flock : public Quackable { public: void add(Quackable* quackable) { quackers.push_back(quackable); } void quack() { for (const auto& e : quackers) { e->quack(); } } void registerObservable(Observer* observer) { for (const auto& e : quackers) { e->registerObservable(observer); } } void notifyObservers() { } private: vector<Quackable*> quackers; };

main.cpp:

#include "compound.h" static void simulate(Quackable* duck) { duck->quack(); } static void simulate(AbstractDuckFactory* duckFactory) { Quackable* redheadDuck = duckFactory->createRedheadDuck(); Quackable* duckCall = duckFactory->createDuckCall(); Quackable* rubberDuck = duckFactory->createRubberDuck(); Quackable* gooseDuck = duckFactory->createGooseDuck(); Flock* flockOfDucks = new Flock(); flockOfDucks->add(redheadDuck); flockOfDucks->add(duckCall); flockOfDucks->add(rubberDuck); flockOfDucks->add(gooseDuck); Flock* flockOfMallard = new Flock(); Quackable* mallard1 = duckFactory->createMallardDuck(); Quackable* mallard2 = duckFactory->createMallardDuck(); Quackable* mallard3 = duckFactory->createMallardDuck(); Quackable* mallard4 = duckFactory->createMallardDuck(); flockOfMallard->add(mallard1); flockOfMallard->add(mallard2); flockOfMallard->add(mallard3); flockOfMallard->add(mallard4); flockOfDucks->add(flockOfMallard); Observer* quackoLogist = new QuackoLogist(); flockOfDucks->registerObservable(quackoLogist); cout << "Duck Simulator : Whole Flock Simulation\n"; simulate(flockOfDucks); //cout << "\nDuck Simulator : Mallard Flock Simulation\n"; //simulate(flockOfMallard); cout << "The ducks quacked " << QuackCounter::getQuacks() << " times" << endl; } int main() { AbstractDuckFactory* duckFactory = new CountingDuckFactory(); simulate(duckFactory); return 0; }

运行结果:

大功告成,我们的观察者模式也运行正确。

这是一个大场面的终局。六个模式一起来创建这个令人惊叹的鸭子模拟器。

十四.总结

这还不是复合模式,是一群模式的合作。我们在日常开发中,不一定要使用某个设计模式,只要能满足业务需求,能达到目的就可以,重要的是封装改变的地方。有时候,只要使用良好的OO设计原则就可以解决问题,这样其实就足够了。

这个书中将许多设计模式揉和在一起的例子显得十分的做作,最后的观察者模式实现我也不认可,因为有大量的代码重复,但也能理解,书中只是为了讲解模式的合作。

http://www.jsqmd.com/news/280079/

相关文章:

  • 解码AI生态新范式,擘画智能未来新图景
  • 基于Springboot+Vue的校园设备维护报修系统(源码+lw+部署文档+讲解等)
  • 瞬维智能:以AI获客智能体重塑房产行业增长逻辑
  • 瞬维智能CEO刘哲先生受邀参加2025年火山引擎FORCE原动力大会
  • 完整教程:【华为云DevUI开发实战】
  • 基于Springboot+Vue的物品租赁管理系统(源码+lw+部署文档+讲解等)
  • 回收沃尔玛购物卡选对平台,京顺回收多赚的钱能再买两箱牛奶
  • 基于Springboot+Vue的乡村信息管理系统(源码+lw+部署文档+讲解等)
  • 实用指南:CentOS Stream 9入门学习教程,从入门到精通,Linux操作系统概述 —全面知识点详解(1)
  • 基于Springboot+Vue的乡镇卫生所医用物资进销存系统(源码+lw+部署文档+讲解等)
  • 基于Springboot+Vue的小型家政服务管理系统(源码+lw+部署文档+讲解等)
  • 吐血推荐专科生必用AI论文写作软件TOP9
  • 基于Springboot+Vue的图书馆座位预约系统(源码+lw+部署文档+讲解等)
  • ChatApis.dll文件丢失找不到 免费下载方法分享
  • 《深度!AI应用架构师助力企业数字化转型的策略深度剖析》
  • ABAP 采购订单开票(MIRO)报错:M8 504 开发票数量大于收货数量 (50 EA)
  • ChxAPDS.dll文件丢失找不到 免费下载方法分享
  • 基于Springboot+Vue的物流管理平台系统(源码+lw+部署文档+讲解等)
  • PPO 为何成了大模型微调“最后的底牌”?一篇真正能跑通的工程实战指南
  • 如何评估AI智能体的能源优化效果?AI应用架构师的指标体系
  • 导师推荐!自考必看TOP10 AI论文写作软件测评
  • 从分布式架构到提示工程,我的知识体系重构之路(全程记录)
  • 打开网站时弹出Accept Cookies(接受Cookie)提示是什么意思?(数据保护法规,欧盟GDPR)
  • 2026广东最新婚纱摄影机构工作室五大推荐!广州优质婚纱摄影工作室定格幸福瞬间
  • ChxHAPDS.dll文件丢失找不到 免费下载方法分享
  • 刘诗诗上海Celine黑衣造型亮相,贵气是与生俱来的天赋
  • 飞书markdown下载(飞书文档转markdown格式)Chrome插件——飞书转存专家、转换markdown转换,markdown飞书下载飞书转换飞书
  • SQL注入原理和防范措施
  • 苏棋闪耀时尚盛典荣获“年度新人” 未来之境见证新星诞生
  • 手把手教你学Simulink--电机控制架构与算法实现​场景示例:基于Simulink的DTC直接转矩控制算法优化仿真