装饰模式:
装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
结构图:
模式的组成:
Component是定义一个对象接口。可以给这些对象动态的添加职责。
ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。
Decorator,装饰抽象类,继承了Component。从外类来扩展Component类的功能。对于Component来说,是无需知道Decorator的存在的。ConreteDecorator就是具体的装饰对象。起到给Component添加职责的功能。
抽象类算法:Component
abstract class Component
{
public abstract void Operation();
}
ConcreteComponent类
class ConreteComponent:Component
{
public override void Operation()
{
Console.WriteLine("具体对象的操作");
}
}
Decorator类
abstract class Decorator:Component
{
protected Component component;
public void SetComponent(Component component)
{
this.component = component;
}
public override void Operation()
{
if(component != null)
{
component.Operation();
}
}
}
具体ConcreteDecorator类:
class ConcreteDecoratorA:Decorator
{
private string addedState;
public override void Operation()
{
base.Operation();
addState = "New State";
Console.WriteLine("具体装饰对象A的操作");
}
}
class ConcreteDecoratorB:Decorator
{
public override void Operation()
{
base.Operation();
AddBehavior();
Console.WriteLine("具体装饰对象A的操作");
}
private void AddedBehavior()
{
// 具体操作B
}
}
客户端调用:
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
举例,对一个人名为小菜的穿着进行包装。在使用装饰类之前的代码可能是这样的:
初级版:
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public void WearTShirts()
{
Console.Write("大T恤 ");
}
public void WearBigTrouser()
{
Console.Write("垮裤 ");
}
public void WearSneakers()
{
Console.WriteLine("破球鞋 ");
}
public void WearSuit()
{
Console.WriteLine("西装 ");
}
public void WearTie()
{
Console.Write("领带 ");
}
public void Show()
{
Console.WriteLine("装扮的{0}",name);
}
}
客户端调用:
class Program
{
static void Main(string[] args)
{
Person xiaocai = new Person("小菜");
Console.WriteLine("\n第一种装扮: ");
xiaocai.WearTShirts();
xiaocai.WearBigTrouser();
xiaocai.WearSneakers();
xiaocai.Show();
Console.WriteLine("\n 第二种装扮:");
xiaocai.WearSuit();
xiaocai.WearTie();
xiaocai.WearLeatherShose();
xiaocai.Show();
}
}
输出:
?从功能上看是实现了装扮的功能。但是这类代码不易维护,如果要添加功能的话,就要修改代码。就需要修改Person类添加功能函数。但是这违背开放封闭原则。所以我们进行一下改进:
输出第二版,对Person类和服饰类进行分离:
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public void Show()
{
Console.WriteLine("装扮的{0}",name);
}
}
abstract class Finery
{
public abstract void Show();
}
子类:
class BigTrouser : Finery
{
public override void Show()
{
Console.WriteLine("垮裤 ");
}
}
class TShirts : Finery
{
public override void Show()
{
Console.WriteLine("T恤 ");
}
}
class Sneakers : Finery
{
public override void Show()
{
Console.WriteLine("破球鞋 ");
}
}
class Suit : Finery
{
public override void Show()
{
Console.WriteLine("西服 ");
}
}
class Tie : Finery
{
public override void Show()
{
Console.WriteLine("领带 ");
}
}
class LeatherShoes : Finery
{
public override void Show()
{
Console.WriteLine("破球鞋 ");
}
}
客户端调用:
class Program
{
static void Main(string[] args)
{
Person xiaocai = new Person("小菜");
Console.WriteLine("\n第一种装扮: ");
Finery dtx = new TShirts();
Finery kk = new BigTrouser();
Finery pqx = new Sneakers();
dtx.Show();
kk.Show();
pqx.Show();
xiaocai.Show();
Console.WriteLine("\n 第二种装扮:");
Finery xz = new Suit();
Finery ld = new Tie();
Finery px = new LeatherShoes();
xiaocai.Show();
}
}
结果同上。这个虽然做到了一定的分离,但是代码中出现了大量的Show()调用。这就是将穿的动作完全暴露出来。这里应该做一个封装。内部调用。
第三种方案走起:
class Person
{
public string name;
public Person()
{
}
public Person(string name)
{
this.name = name;
}
public virtual void Show()
{
Console.WriteLine("装扮的{0}", name);
}
}
class Finery : Person
{
protected Person component;
public void Decorate(Person component)
{
this.component = component;
}
public override void Show()
{
if (component != null)
{
component.Show();
}
}
}
子类:
class BigTrouser : Finery
{
public override void Show()
{
Console.WriteLine("垮裤 ");
base.Show();
}
}
class TShirts : Finery
{
public override void Show()
{
Console.WriteLine("T恤 ");
base.Show();
}
}
class Sneakers : Finery
{
public override void Show()
{
Console.WriteLine("破球鞋 ");
base.Show();
}
}
class Suit : Finery
{
public override void Show()
{
Console.WriteLine("西服 ");
base.Show();
}
}
class Tie : Finery
{
public override void Show()
{
Console.WriteLine("领带 ");
base.Show();
}
}
class LeatherShoes : Finery
{
public override void Show()
{
Console.WriteLine("破球鞋 ");
base.Show();
}
}
客户端调用:
class Program
{
static void Main(string[] args)
{
Person xiaocai = new Person("小菜");
Console.WriteLine("\n第一种装扮: ");
Sneakers pqx = new Sneakers();
BigTrouser kk = new BigTrouser();
TShirts dtx = new TShirts();
pqx.Decorate(xiaocai);
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(xiaocai);
ld.Decorate(px);
xz.Decorate(ld);
xz.Show();
}
}
效果:
子类的每次装饰都会调用父类的Show方法。这样就将Show方法隐藏起来。好了,这就是今天介绍的装饰模式。
|