目录
一.专栏简介
本专栏是我学习《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设计原则就可以解决问题,这样其实就足够了。
这个书中将许多设计模式揉和在一起的例子显得十分的做作,最后的观察者模式实现我也不认可,因为有大量的代码重复,但也能理解,书中只是为了讲解模式的合作。