类关系图


类角色说明
· 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
· 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
· 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
· 具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。

意图
装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。主要用途,是在不改变一个类的代码、也不改变它的继承体系的前提下,为这个类增加功能。当你可能想为一个类增加更多功能时,使用装饰者模式意味着你的新版本的代码不必通过继承这个类来重用现有的功能。

适用性
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。   
处理那些可以撤消的职责。   
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

泡妞的例子
DECORATOR —Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写上“最好的的礼物,就是爱你的7in10”,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……,我们都是Decorator,最终都在修饰我这的相片呀,怎么样,看懂了吗?

泡妞的代码
using System;
using System.Collections;

 
// "Component"    抽象角色
public abstract class 抽象构件
{
    
private string name;
    
public string Name
    
{
        
get{return name;}
        
set{name=value;}
    }

    
public abstract void Display();
}


// "ConcreteComponent"具体构件角色
public class 华山相片:抽象构件
{
    
public override void Display()
    
{
        Console.WriteLine(
"我在华山顶上的照片!");
    }

}


// "Decorator"装饰角色:关键所在,一个抽象的装饰角色继承自抽象的构件。
public abstract class 装饰者:抽象构件
{
    
protected 抽象构件 相片;
    
public 装饰者(抽象构件 某张相片)
    
{
        相片
=某张相片;
    }

    
public override void Display()
    
{
        相片.Display();
    }

}


// "ConcreteDecorator"具体装饰角色
public class 实际装饰者1:装饰者
{
    
private string 祝福语;
    
public 实际装饰者1(抽象构件 某个需被装饰的构件):base(某个需被装饰的构件){}
    
public void 写字()
    
{
        祝福语
="最好的的礼物,就是爱你的7in10!";
    }

    
public override void Display()
    
{
        
base.Display();
        Console.WriteLine(祝福语);
    }

}


// "ConcreteDecorator"具体装饰角色
public class 实际装饰者2:装饰者
{
    
private string 相框;
    
public 实际装饰者2(抽象构件 某个需被装饰的构件):base(某个需被装饰的构件){}
    
public void 包装()
    
{
        相框
="这个相片配上这个相框真是漂亮极了,女孩子一定会喜欢的!";
    }

    
public override void Display()
    
{
        
base.Display();
        Console.WriteLine(相框);
    }

}


// "ConcreteDecorator"具体装饰角色
public class 实际装饰者3:装饰者
{
    
private string 礼品盒;
    
public 实际装饰者3(抽象构件 某个需被装饰的构件):base(某个需被装饰的构件){}
    
public void 设计()
    
{
        礼品盒
="这个礼品盒可真别致,女孩子一定会喜欢的!";
    }

    
public override void Display()
    
{
        
base.Display();
        Console.WriteLine(礼品盒);
    }

}


public class MyClass
{
    
public static void Main()
    
{
        华山相片 相片
=new 华山相片();
        实际装饰者1 me
=new 实际装饰者1(相片);
        me.写字();
        实际装饰者2 mm
=new 实际装饰者2(me);
        mm.包装();
        实际装饰者3 mike
=new 实际装饰者3(mm);
        mike.设计();
        
        mike.Display();
    }

}

装饰模式
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。

注意
装饰模式和适配模式中的对象适配方式的区别。
他们都是通过调用一个成员变量,将自己的方法接口和成员变量的方法接口统一起来。但是他们最大的特点是在各自初始化的函数中,装饰模式有参数,对象适配方式没有参数。装饰模式是通过一个参数来为成员变量赋值。而对象适配方式是通过成员变量对象本身的初始化来为其赋值。另外装饰模式应该还有其他附加接口来扩充功能。

优缺点
优点
1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
3. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错。
使用装饰模式主要有以下的缺点:
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

说明
我不知道这个例子能不能说明问题。可能有些朋友看了还是会有些糊涂。我再大概举个例子说明一下,加深理解。
孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成雀儿时,就可以在天上飞行。而不管悟空怎么变化,在二郎神眼里,他永远是那只猢狲。对于这个例子模型应该是这样的:
有一个抽象角色Component定义了一些基本的方法比如孙悟空和鸟的吃食的动作
从Component继承下来一个具体构件角色Concrete Component 就是孙悟空了
从Component继承下来一个装饰角色Decorator,是所有孙悟空的变身的接口类,这个类中应该有一个抽象角色作为成员对象,也应该有方法是将一个Component抽象角色作为参数附给这个成员对象,实际上就是将孙悟空赋值给抽象角色了
从Decorator继承下落一个具体装饰角色Concrete Decorator,就是鸟啊之类的,可以为这个类增加有特色的方法,比如鸟的Fly()等等。
实际在客户端调用的时候,应该先有Concrete Decorator,然后将Concrete Component赋给Concrete Decorator的成员变量后调用Concrete Decorator的特殊接口动作。
 齐天大圣 c = new 大圣本尊();
 雀儿 bird = new 雀儿(c);
 bird.fly();

装饰模式的关键是被装饰完成后的对象与完成前的对象有相同的接口,所扩充的是职责,但接口并没有改变。换句话说,如果装饰器的引入使接口发生了变化那就不再是装饰器模式了。
posted on 2007-01-07 20:02  十分之七  阅读(329)  评论(0)    收藏  举报