这个模式理解起来有些难度,本人也是通过看书、上网查资料,才了解了一些,下面来讲解一些其中的道理吧!
装饰模式是什么?
定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
白话说:动态的扩展对象的功能
UML图如下:
角色扮演:
1、抽象构件(Component):给出一个抽象接口,以规范准备接收附加责任的对象
2、具体构件(Concrete Component):定义一个将要接收附加责任的类
3、装饰(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
4、具体装饰(Concrete Decorator):负责给构件对象“贴上”附加的责任
有时候我们会发现有些情况我们抽象不出以上几种角色,这个时候我们需要进行一些改动:
1、如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
2、如果只有一个ConcreteDecortor类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类
说了这么多,我们也许还会有些蒙圈,现在就让我们用实在的例子去理解吧!
先看一下小菜穿衣服的例子
UML结构图如下:
解说:这里人相当于具体构件(ConcreteComponent),服饰相当于装饰角色(Decorator),下面那些衣服相当于具体的服饰,这个例子中没有抽象构件!
代码如下:
Person类,相当于ConcreteComponent
class Person
{
public Person()
{}
private string name;
public Person(string name)
{
this.name = name;
}
public virtual void show()
{
Console.WriteLine("装扮的{0}", name);
}
}
服装类(Decorator)
class Finery : Person
{
protected Person component;
//打扮
public void Decorate(Person component)
{
this.component = component;
}
public override void show()
{
if (component != null)
{
component.show();
}
}
}
具体服饰类
class TShirts : Finery
{
public override void show()
{
Console.Write("大T恤!");
base.show();
}
}
class BigTrouser : Finery
{
public override void show()
{
Console.Write("垮裤!");
base.show();
}
}
class Sneakers : Finery
{
public override void show()
{
Console.Write("破球鞋");
base.show();
}
}
class LeatherShoes : Finery
{
public override void show()
{
Console.Write("皮鞋");
base.show();
}
}
class Tie : Finery
{
public override void show()
{
Console.Write("领带");
base.show();
}
}
class Suit : Finery
{
public override void show()
{
Console.Write("西装");
base.show();
}
}
客户端代码:
Person xc = new Person("小菜");
Console.WriteLine("\n第一种装扮:");
Sneakers pqx = new Sneakers();
BigTrouser kk = new BigTrouser();
TShirts dtx = new TShirts();
pqx.Decorate(xc);
kk.Decorate(pqx);
dtx.Decorate(kk);
dtx.show();
Console.WriteLine("\n第二种装扮:");
LeatherShoes px = new LeatherShoes();
Tie ld = new Tie();
Suit xz = new Suit();
px.Decorate(xc);
ld.Decorate(px);
xz.Decorate(ld);
xz.show();
Console.ReadKey();
注意:Person类、服装类、具体服饰类之间的关系是继承,客户端的代码直接调用他们
那么什么时候用装饰模式呢?
1、装饰者和被装饰对象具有相同的类型
2、可以用一个或多个装饰者包装一个对象
3、由于装饰者和被装饰对象有相同的类型,所以在任何需要原始对象的场合,都可以用装饰过的对象代替他
4、装饰者可以在所委托被装饰着的行为之前或之后,加上自己的行为,以达到特定的目的
5、对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用需要的装饰者来装饰对象