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

目录

一.专栏简介

二.模式合作

三.与鸭子重聚

1.创建一个Quackable接口

2.鸭子实现Quackable

3.模拟器

四.加上鹅

五.鹅适配器

六.模拟器中加入鹅

七.叫声的统计

八.模拟器加入装饰者

九.工厂生产鸭子

十.模拟器使用工厂

十一.创建一群鸭子

十二.修改模拟器

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

十四.总结


一.专栏简介

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

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

二.模式合作

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

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

三.与鸭子重聚

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

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

1.创建一个Quackable接口

cpp 复制代码
struct Quackable
{
	virtual void quack() = 0;
};

2.鸭子实现Quackable

cpp 复制代码
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.模拟器

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

cpp 复制代码
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;
}

运行结果:

四.加上鹅

cpp 复制代码
class Goose
{
public:
	void honk()
	{
		cout << "Honk" << endl;
	}
};

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

五.鹅适配器

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

六.模拟器中加入鹅

cpp 复制代码
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;
}

运行结果:

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

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

七.叫声的统计

cpp 复制代码
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;
};

八.模拟器加入装饰者

cpp 复制代码
#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;
}

运行结果:

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

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

九.工厂生产鸭子

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

cpp 复制代码
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());
	}
};

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

十.模拟器使用工厂

cpp 复制代码
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来说,组合模式最合适不过了!

让我们逐步看如何运作:

cpp 复制代码
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里的那个语法糖循环。

十二.修改模拟器

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

	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:

cpp 复制代码
#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:

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设计原则就可以解决问题,这样其实就足够了。

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

相关推荐
zmzb01032 小时前
C++课后习题训练记录Day74
开发语言·c++
S-X-S2 小时前
常用设计模式+集成websocket
websocket·设计模式
代码游侠2 小时前
学习笔记——时钟系统与定时器
arm开发·笔记·单片机·嵌入式硬件·学习·架构
cdut_suye2 小时前
解锁函数的魔力:Python 中的多值传递、灵活参数与无名之美
java·数据库·c++·人工智能·python·机器学习·热榜
诸葛成2 小时前
渗透测试-信息收集
经验分享·笔记·课程设计
峰顶听歌的鲸鱼3 小时前
Kubernetes管理
运维·笔记·云原生·容器·kubernetes·云计算
txinyu的博客3 小时前
前置声明与 extern
linux·c++
Zach_yuan4 小时前
面向对象封装线程:用 C++ 封装 pthread
开发语言·c++·算法
zhangrelay4 小时前
影响移动固态磁盘稳定性的原因有哪些呢?
笔记·学习