设计模式之装饰模式

来源:互联网 发布:类似于淘宝的购物软件 编辑:程序博客网 时间:2024/05/20 17:27

装饰模式,动态的给一个对象添加一些额外的职责。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

一、装饰模式角色组成:

抽象构件(Component):给出一个抽象接口,可以给这些对象动态的添加职责。

具体构件(ConcreteComponent):定义一个将要接收附加责任的类。

装饰类(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

具体装饰角色(ConcreteDecorator):负责给构件对象“贴上”附加的责任。

二、案列分析:

我们通过西游记第二十七回《尸魔三戏唐三藏 圣僧恨逐美猴王》中孙悟空三打白骨精的故事学习一下装饰模式。

书中这样描写:

好妖精,停下阴风,在那山凹里,摇身一变,变做个月貌花容的女儿,说不尽那眉清目秀,齿白唇红。
……
好妖精,按落阴云,在那前山坡下,摇身一变,变作个老妇人,年满八旬,手拄着一根弯头竹杖,一步一声的哭着走来。
……
好妖怪,按耸阴风,在山坡下摇身一变,变成一个老公公,真个是:白发如彭祖,苍髯赛寿星….”

案列分析:

白骨精(Decorator)属于妖怪(Component),妖怪的职责就是要吃唐僧肉,假变女子、老妇、老汉(这些都是ConcreteDecorator)要吃唐僧。这就是一个装饰模式的体现,其UML图如下:

这里写图片描述

具体代码:

妖怪–Component 抽象类

abstract class Monster(){    public abstract void eatTS();}

妖怪实现类–ConcreteComponent 类:

public class ConcreteMonster extends Component {   public void eatTS(){     System.out.println("我们是妖怪,我要吃唐僧");   }}

白骨精–Decorator 类:

public class WhiteBoneMonster extends Component {    protected Component component ;   public void SetComponent(Component component){    this.component = component ;   }   public void eatTS(){    component .eatTS();   }}

女子–ConcreteDecorator类

public class Daughter extends WhiteBoneMonster {    private String description;  public void eatTS(){     super.eatTS();     description= "翠袖轻摇笼玉笋,湘裙斜拽显金莲";     System.out.println("我是一个"+description+"的女子");   }}

老妇–ConcreteDecorator类

public class Grandma extends WhiteBoneMonster {    private String description;  public void eatTS(){     super.eatTS();     description= "年满八旬";     System.out.println("我是"+description+"的老母,我来找我女儿。");   }}

老汉–ConcreteDecorator类

public class Grandfa extends WhiteBoneMonster {    private String description;  public void eatTS(){     super.eatTS();     description= "一生好善斋僧,看经念佛";     System.out.println("我是"+description+"的老汉,我来找我妻女。");   }}

故事上演:

public void story(){ public static void main(String [] args){   WhiteBoneMonster wbm = new WhiteBoneMonster ();   Daughter daughter = new Daughter ();   Grandma  grandma  = new Grandma ();   Grandfa  grandfa  = new Grandfa ();   daughter.setComponent(wbm);   grandma.setComponent(daughter);   grandfa.setComponent(grandma);   grandfa.eatTS(); }}

运行结果如下:

我们是妖怪,我要吃唐僧!我是一个翠袖轻摇笼玉笋,湘裙斜拽显金莲的女子。我是年满八旬老母,我来找我女儿。我是一生好善斋僧,看经念佛的老汉,我来找我妻女。

装饰模式的好处在上面的案列中,体现在,只要随便调用某一个角色的eatTS()方法,就能知道之前发生了什么!!

三、装饰模式总结

每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。它是由Decorator的SetComponent方法来实现的,因此它们的职责是单一的。

Decorator抽象类中,持有Component接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。

Decorator抽象类的子类(具体装饰者),里面都有一个构造方法调用super.eatTS(),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是Component接口,只要是该Component的实现类都可以传递进去,即上面测试类的代码也可以写成:

 Grandfa  grandfa  =  new Grandfa (new Grandma (new Daughter (new WhiteBoneMonster ()))); grandfa.eatTS();

这种结构的样子。所以当调用grandfa.eatTS()的时候,又因为每个具体装饰者类中,都先调用super.eatTS()方法,而该super指向了具体的某一个装饰者类,那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。

装饰模式中,如果只有一个ConcreteComponent类而没有抽象的Component,那么Decorator类可以是ConcreteComponent的一个子类。上面的UML图可以简化如下:

这里写图片描述

注:以上的案列分析,可能有些牵强,但装饰模式的主要思路还是能理解一些的。

原创粉丝点击