(learn&think)

不浮躁,不自傲,学习,思考,总结

浅谈设计模式十: 模板方法模式(Template Method)

| Comments

1 实例

有些人喜欢喝茶,有些人喜欢喝咖啡,所以现在有咖啡和茶两个类,基本代码如下:

Coffee 类:

class Coffee {
 public:
  virtual ~Coffee();
  void prepareRecipe();
 protected:
  void boilWater();
  void brewCoffeeGrinds();
  void pourInCup();
  void addSugarAndMilk();
};

Tea 类:

class Tea {
 public:
  virtual ~Tea();
  void prepareRecipe();
 protected:
  void boilWater();
  void steepTeaBag();
  void pourInCup();
  void addLemon();
};

我们发现代码有重复: void boilWater()void pourInCup() 。那么如何整合代码消除重复代码呢?

浅谈设计模式九: 外观模式(Facade)

| Comments

1 实例

在家组建了一个家庭影院,基本配置如下图。每次看电影都要进行如下一系列准备工作:

  1. 打开爆米花机
  2. 爆米花机制作爆米花
  3. 调暗灯光
  4. 投影幕布降下来
  5. 打开投影机

。。。等等

至少在 10 项的准备工作,如果每次一一去调用,非常的繁琐,那么如何让用户方便而简洁的准备看电影,并看完电影善后等活动呢?

浅谈设计模式八: 适配器模式(Adapter)

| Comments

1 实例

如果有一只乌龟走的像一只鸭子,发生声音也类似鸭子,鸭子的接口已经存在了,现在想把乌龟添加到鸭子实例的调用者里,那么调用者能如何继续用鸭子的接口去调用乌龟呢?

浅谈设计模式七: 命令模式(Command)

| Comments

1 实例

有一个远程控制器,上面有很多按钮,每个按钮分配不同的功能,比如打开客厅灯,关闭客厅灯,调高风扇的风力,关闭风扇等。那么整个家庭会有如下那么多的控制对象,如何很好的维护,易扩展,易独立改变呢?

浅谈设计模式六: 单例模式(Singleton)

| Comments

1 实例

对于一些类来说只有一个实例是很重要的。如,仅有一个文件系统,一个窗口管理者。一个数字滤波器只有一个模数转换器。

那么我们如何确保一个类只有一个实例,而且这个实例能容易的访问?

  1. 全局变量。一个全局变量能使对象任意访问,但是它并不能防止你实例化多个对象。
  2. 单例模式。更好方法是让类自己负责保存它唯一的实例。这个类能保证没有其他实例被创建(通过截断创建新对象的请求),而且它提供获取这个实例的方法。

浅谈设计模式五: 抽象工厂模式(Abstract Factory)

| Comments

1 实例

继续扩展模式四中的批萨店实例,加入批萨配料对象。不同的地区的批萨店有一组共同的产品(如生面,酱汁,芝士等等),但是根据不同地区的口味有不同的实现。整个系统变得有点复杂了,

  1. 有不同的批萨原料,同样的批萨原料在不同的地区有不同的作法;
  2. 每个店有不同种类的批萨(即各种原料搭配不同);
  3. 整个批萨连锁在不同地区有不同的店。

如何清晰而易维护的设计整个批萨连锁店系统呢?

浅谈设计模式四: 工厂模式(Factory Method)

| Comments

1 实例

批萨店有各种不同的批萨,根据不同的用户来点批萨,基本实现如下:

Pizza* orderPizza(string type) {
  Pizza pizza = NULL;
  if (type == "cheese") {
    pizza = new CheesePizza();
  } else if (type == "pepperoni") {
    pizza = new PepperoniPizza();
  } else if (type == "clam") {
    pizza = new ClamPizza();
  } else if (type == "veggie") {
    pizza = new VeggiePizza();
  }
  pizza->prepare();
  pizza->bake();
  pizza->cut();
  pizza->box();
  return pizza;
}

但是如果批萨店新添或下架其它的品种的批萨呢?就需要在这个函数里添加或删除不同的批萨,而这段代码包括变化的批萨品种,和不变的批萨制作过程。不易后期维护。

浅谈设计模式三: 装饰器模式(Decorator)

| Comments

1 实例

星巴克以咖啡文明,现在为它设计它的咖啡订餐系统。

  1. 先定义一类饮料的基类 Beverage ,为不同咖啡做好一个接口。
  2. 每种不同的咖啡继承这个基类,覆盖各自的特性,比如描述,价格等。

每种咖啡都有很多中附加,比如拿铁咖啡就有,加糖拿铁,加奶拿铁,加奶加糖拿铁等等。所以按照上面的设计来设计咖啡订餐系统,那么整个系统类结构如下:

每种咖啡不同的附加组合导致太多类。

浅谈设计模式二: 观察者模式(Observer)

| Comments

1 实例

有一个气候观测应用,包括三部分:

  1. 气候站(WeatherStation):物理设备用来采集实际天气数据;
  2. 气候数据对象(WeatherData)追踪来自气候站的数据和更新显示;
  3. 给用户现在气候情况的显示(xxDisplay)

现在气候收集这 3 个数据:温度,湿度和气压。有 3 种不同的显示:现在的天气情况,天气统计信息和天气预测信息。

直观的话是在 WeatherData 类里的 measurementsChanged() 里直接调用不同显示器的 update() 来更新数据,如下:

WeatherData::measurementsChanged() {
currentConditionsDisplay.update(temp_, humidity_, pressure_);
statisticsDisplay.update(temp_, humidity_, pressure_);
forecastDisplay.update(temp_, humdity_, pressure_);

1. WeatherData 和 Display 比较紧的耦合。在函数内直接使用实例,每次增加或较少 Display 都要在这个函数内修改。
2. 以具体实例来编码,使得不能动态的添加和减少显示元素,唯有修改这段代码

浅谈设计模式一: 策略模式(Strategy)

| Comments

1 实例

有一个模拟鸭子的应用完成。这个应用可以仿真鸭子的各种活动,比如游泳,鸣叫,飞等等。能马上想到的模式设计如下:

一个基类 Duck 定义 Duck 的一些特性,子类继承它的特性,并覆盖它的部分特性。至此没什么问题。子类共同拥有父类的特性,消除了代码的重复性。

然后想让 Duck 具有有 fly() 的特性,把它加到父类中,相应的不同 duck(子类)如果不具备 或 fly()quack 的特性,那么就去覆盖父类相应的特性。

每增加一个不同的子类 duck,如果没有父类相应的特性都要去覆盖它,很冗余。

那么如果把不变的特性继续放在基类 Duck 里,而把变化的特性拿出来做成独立的接口呢?

1. 增加代码的冗余性,每个子类 duck 都要去实现部分相同的特性;2. 想更改一个相同的 fly() 特性,要在相应的所有子类都修改