装饰者模式

设计模式

最近买了本设计模式的书Header First 非常喜欢其中的讲解方式。虽然买了有一段时间了但是没有认真的看过。这段时间工作相对没有那么难了,所以抽出点时间看一下这本书,同时,在这里做一下分享,希望可以帮到你!

1、定义

装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

给爱用继承的人一个全新的设计眼界

2、使用场景

比如,我们现在有一个需求,建设一个。首先我们需要房子,其次我们需要去装修这所房子。很明显在装修的过程中我们可能要用很多的材料,而且还要买很多的家具。那么在我做预算的时候我就要知道这个家的总造价,那么我如何更快更好的获取到这个房子的总造价呢?

由于每个家具的造价是不相同的,而具体的价格只有家具本身最清楚。因此简单的讲,我们可以设置一个父类(家),各种家具作为子类。父类针对每一个子类拥有两个属性(是否使用这个家具,这个家具的价格是多少)。这样父类在计算总价格的时候就可以通过判断是否使用某一类家具,如果使用那么在计算的时候就加上这个家具的价格

但是,每次我要添置一个新的家具,我就要修改父类中的方法,这完全违背了我们面向对象的设计原则。这时候就该装饰者模式大显身手了。

装饰者模式,其实说白了就是组合的方式,存在一个主体,同时也存在很多与主体同类型的装饰品,一个复杂的主题可以通过一个单纯的主题和许多装饰品通过复杂的组合方式组合成一个复杂的主题。

例如,我们有一个房子,这个房子作为主体,同时我们还有很多家具(家具和房子都是我们的子类),我们从这些子类中选择一个作为主体(房子),选择其他的作为装饰者(家具等),这样我们通过组合就能组合出一个漂亮的。这其中要注意哪一个是主题哪一个是主题,哪一个是装饰者。

3、思考

咦?????,我们在使用装饰者模式,家具和房子都是我们的家的子类,这么明显的继承,显然违背了我们少用继承多用组合的设计原则啊!什么鬼!!!

这里我们的确是使用了继承,但是要注意,我们这里使用继承的目的和使用继承与之前的区别。

这里我们使用继承的目的是使装饰者和被装饰者是相同类型,也就是说有共同的父类。

这里的继承与以往不同,以往的继承我们主要是想做到一些方法或者属性的继承,属于功能性的继承,但是这里我们的继承属于类型继承。

这样,我们的装饰者和被装饰者属于同一种类型,那么我们在使用的时候就可以使用装饰者取代被装饰者,或者使用被装饰者取代装饰者。

4、修改思路

那么我们如何使用装饰者模式去实现我们的这个需求呢。

首先我们的家具和房子必须同属一个父类(确保二者的类型是相同的,保证互相可代替性)。

其次:作为主体,我们从父类继承了一个方法(比如cost()价格),对于其他的装饰者,我们也实现一个cost()方法。

我们如果要计算总的造价,比如要计算一个带有冰箱,电视机,空调,洗衣机的房子的总造价。那么最简单的方法是计算一个带冰箱的家的造价+带电视机的家的造价+带空调、洗衣机的家的造价+房子的造价 = 总造价。

对于装饰者和被装饰者的关系,可以通过下图来表述

关系图

5、具体实现

  • 1、确定一个父类(Family)
  • 2、这个父类有两个子类(装饰者和被装饰者)家具和房子
  • 3、对于装饰者,每一个装饰者都有一个属性(family)一个方法cost()
    一个构造函数(传入family的初始值),同时cost方法是将属性family
    的cost()+自己的价格
1
2
3
4
5
    cost() {

return 0.4 + family.cost();

}
  • 4、对于被装饰者,我们要实现一个cost()方法

我们计算总造价的时候,是通过:

1
2
3
4
5
6
7
8
9
10
11
12
Family *f1 = house();

f1 = bridge(f1);

f1 = washmachine(f1);

f1 = tv(f1);

f1 = aircondition(f1);

nslog(f1.cost());

通过这种方式我们可以计算出房子的具体造价,具体实现的如下图所示:

具体实现

具体的代码实现放到这里