news 2026/7/22 7:25:37

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于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设计原则就可以解决问题,这样其实就足够了。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 16:48:28

基于Springboot+Vue的物品租赁管理系统(源码+lw+部署文档+讲解等)

课题介绍本课题针对物品租赁行业租赁流程繁琐、物品状态难追踪、押金核算复杂、租赁数据零散等痛点&#xff0c;设计并实现基于SpringbootVue的物品租赁管理系统&#xff0c;构建集物品管理、租赁交易、押金管控、数据统计于一体的数字化租赁运营平台。系统以MySQL为数据存储核…

作者头像 李华
网站建设 2026/7/21 13:44:54

基于Springboot+Vue的校园闲置物品租售系统(源码+lw+部署文档+讲解等)

课题介绍 本课题针对校园内闲置物品流转不畅、交易信息分散、供需匹配低效、线下租售安全性不足及模式单一等痛点&#xff0c;设计并开发基于SpringbootVue的校园闲置物品租售系统&#xff0c;构建集物品发布、租售管理、检索匹配、在线沟通、履约追踪于一体的数字化校园服务平…

作者头像 李华
网站建设 2026/7/21 15:42:18

回归测试:软件演进中的质量守护神与实践全指南

回归测试作为软件质量保障的核心支柱&#xff0c;在持续交付和敏捷开发时代的重要性日益凸显。本文系统性地探讨了回归测试的理论基础、技术策略和实施框架&#xff0c;为企业构建高效、可持续的回归测试体系提供了一套完整的方法论。通过分层策略、选择性测试和智能自动化相结…

作者头像 李华
网站建设 2026/7/21 16:15:27

手把手教你学Simulink--电机控制架构与算法实现​场景示例:基于Simulink的电机电流环PI参数整定仿真

目录 手把手教你学Simulink 一、引言:为什么“调不好PI”会让高性能电机变成“抖动机器”? 二、核心原理:电流环的“等效传递函数”建模 1. 电流环简化模型(d/q轴解耦后) 2. 数字控制系统中的关键延迟 3. 电流环闭环结构 三、应用场景:伺服驱动器中的高性能电流环…

作者头像 李华
网站建设 2026/7/20 23:46:19

大模型推理入门:全流程深度解析

前言 大模型推理的核心定义&#xff0c;本质上是基于已训练完成的大模型参数&#xff0c;给定输入信息后&#xff0c;通过模型的计算逻辑生成符合任务要求的输出结果的过程。它和大模型训练是完全不同的两个阶段&#xff0c;训练的核心是通过海量数据迭代更新模型的权重参数&am…

作者头像 李华
网站建设 2026/7/1 16:35:30

苏棋闪耀时尚盛典荣获“年度新人” 未来之境见证新星诞生

当星光在深圳湾的夜空流淌&#xff0c;时尚之夜暨时尚传媒集团32周年盛典如期揭开华幕。这座被誉为“未来之城”的科技腹地&#xff0c;化身为一艘满载瑰丽想象的航船&#xff0c;载着影视、音乐、艺术等各领域最耀眼的星辰&#xff0c;驶向名为“未来之境”的彼岸。在这璀璨星…

作者头像 李华