浅析设计模式:装饰模式(Decorator)

学习装饰模式之前,我们先来看一个案例:

       大家都吃过蛋糕,但是蛋糕是怎么做出来的呢?我们不妨这么猜测:首先蛋糕师会烘焙出一个蛋糕,然后摆上了货柜。这时来了一个顾客,他要买奶油蛋糕,蛋糕师会怎么做 ?最简单的方式当然是将货柜上已经烘焙好的蛋糕取出来,涂上一层奶油,奶油蛋糕就做好了!顾客提出新的需求,例如购买草莓奶油蛋糕,同理只需要在奶油蛋糕的基础上摆上一些草莓即可。

        上述案例中,将原始蛋糕不断添加新元素的过程就是装饰模式,蛋糕师不需要将所有类型的蛋糕全部制作成成品,这样成本太大,蛋糕师只需要准备好一个烘焙好的蛋糕(被装饰物)和一些辅料(装饰边框),然后根据顾客的需求,往蛋糕上添加辅料即可实现组合口味的蛋糕。编程的过程就像制作蛋糕的过程,我们不可能穷尽所有需求并将其全部实现,但我们能在原始功能的基础上通过不断装饰,使得功能更加明确具体(功能定制化),最后满足我们的需求。

装饰模式中的角色:

  • Component:(被装饰物) 

         增加功能前的核心角色,上述例子中刚烘焙出来的蛋糕就是Component角色,Component只是定义了蛋糕的接口(API)。

  • Concrete Component:(具体的被装饰物)

       该角色是实现了Component所定义接口的具体的蛋糕,如奶油蛋糕。

  • Decorator:(装饰物)

        该角色与Component具有相同的接口(API),在它内部保存了被装饰对象---Component角色。

  • Concrete Decorator:(具体的装饰物)

      该角色是具体的Decorator。

看到这里云里雾里?没关系,我们可以从类图中理解他们之间的关系:



接下来编程,模拟一个装饰模式的使用案例!

需求:假设我们需要一个打印字符串的功能

Step One:实现Component角色


    DisPlay表示Component角色,可以理解为原始蛋糕的角色。它是一个抽象类,代表着"打印字串"的功能,show方法已经提供具体实现,不允许子类重写(这里隐含了模板模式)。

Step Two:实现ConcreteComponent角色


      StringDisplay类是Display类的子类,承担ConcreteComponent角色,可以理解为具体的蛋糕,如草莓蛋糕。StringDisplay的功能是打印一行字符串。因此getRows方法返回固定值1;getColumns方法返回的是字符串的字符数;getRowText方法只有在行数为0时才返回字符串。

Step Three:实现Decorator角色


    Border类也是DisPlay类的子类,它表示Decorator角色,可以理解为做蛋糕的辅料的抽象类,内部含有Display类的实例,该实例表示"被装饰物",为什么打引号?因为这里的"被装饰物"既可能是真正的被装饰物(原始蛋糕),也可能是已经装饰了被装饰物的"中间层被装饰物"(装饰了原始蛋糕的奶油蛋糕),哈哈这里有点拗口,但是应该还是不难理解的大笑就像剥洋葱,每当剥了一层皮(装饰物),以为要发现芯(被装饰物)了,结果发现还是皮。

Step Four:实现Concrete Decorator角色


    SideBorder是Border类的子类,表示具体的装饰物(往蛋糕两侧涂奶油生气),它的功能是在内部this.display打印功能的基础上,在两侧添加字符,例如this.display打印效果是“hello,world.”,那么SideBorder实现的打印效果就是“#hello,world.#”。

Step Five:根据需求实现其他的Concrete Decorator角色

    除了上述的SideBorder在两侧添加字符,根据需求可以继续编写其他的装饰物角色,如向上下两侧添加字符等,这里不赘述了。

Step Final:编写测试类


    StringDisplay类就是原始的蛋糕,SideBorder类就是在原始蛋糕左右两侧涂上奶油偷笑就是这么个思想,要想把蛋糕上下左右都涂上奶油怎么办?在编写一个实现上下涂奶油的装饰物,然后构造实例时,将SideBorder实例作为参数传给构造方法就好了!

     装饰模式就是通过这种不断的装饰过程,使得类的功能更加具体更加明确!

java源码中也有使用装饰模式的案例:


   Reader就是Component角色,FileReader就是ConcreteComponent角色,而BufferedReader就是ConcreteDecorator角色,FileReader的读取文件功能经过BufferedReader装饰使其具有缓存功能...

















猜你喜欢

转载自blog.csdn.net/someonemh/article/details/80591295