意图/定义:动态地给一个对象添加一些额外的职责,而这些职责可能以任意的顺序来添加,从而提供了比生成子类更灵活的方法来添加功能
问题:要使用的对象可以提供所需的功能,但可能要为这个对象添加某些功能,这些附加功能可能发生在对象的基础功能之前或之后。
参与者与协作者:被装修者让装修者为自己添加功能,但其不需要了解自己被如何装修。
效果:所添加的功能放在小对象中,可以在被装修者之前或之后动态的添加及装配功能,各层的装饰者只知道自己包装了某个被装饰对象,但其不了解这个被包装对象已经被如何包装,也不知道自己将被如何装修。
实例代码,下面的代码展示了在RPG游戏系统中常见的一个实现。我们的角色需要通过装配不同的衣服、武器、挂件等以获得额外属性或技能,而且我们的衣服或武器也可以再镶嵌不同宝石获取额外的属性。这样的功能通常就可以用装修器模式来实现。
在上面的例子中,被装饰类为普通的角色role,其具备基本的三个属性,体力、攻击力、防御力,这三个属性会随着角色不断的装备不同的挂件而进行改变,不同的挂件可以动态的附着在一个被包装的role,并增加其自身的功能。using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Decorator { /// <summary> /// MainApp startup class /// Decorator Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Create ConcreteComponent and two Decorators role r = new role(); clothes c = new clothes(); weapon w = new weapon(); diamond d = new diamond(); // Link decorators c.SetComponent(r); w.SetComponent(c); d.SetComponent(w); d.getRoleAttrbute(); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Component' abstract class /// </summary> abstract class Component { public abstract int[] getRoleAttrbute(); } /// <summary> /// The 'ConcreteComponent' class /// </summary> class role : Component { private int HP; private int ATTACK; private int DEFEND; public role() { HP = ATTACK = DEFEND = 100; } public override int[] getRoleAttrbute() { int[] temp = {HP,ATTACK,DEFEND}; return temp; } } /// <summary> /// The 'Decorator' abstract class /// </summary> abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override int[] getRoleAttrbute() { return component.getRoleAttrbute(); } } /// <summary> /// The 'ConcreteDecoratorA' class /// </summary> class clothes : Decorator { public override int[] getRoleAttrbute() { int[] temp = AddedBehavior(); Console.WriteLine("clothes: {0:d} {1:d} {2:d}", temp[0],temp[1],temp[2]); return temp; } int[] AddedBehavior() { int[] temp = base.getRoleAttrbute(); temp[2] += 10; return temp; } } /// <summary> /// The 'ConcreteDecoratorB' class /// </summary> class weapon : Decorator { public override int[] getRoleAttrbute() { int[] temp = AddedBehavior(); Console.WriteLine("weapon: {0:d} {1:d} {2:d}", temp[0], temp[1], temp[2]); return temp; } int[] AddedBehavior() { int[] temp = base.getRoleAttrbute(); temp[1] += 20; return temp; } } class diamond : Decorator { public override int[] getRoleAttrbute() { int[] temp = AddedBehavior(); Console.WriteLine("diamond: {0:d} {1:d} {2:d}", temp[0], temp[1], temp[2]); return temp; } int[] AddedBehavior() { int[] temp = base.getRoleAttrbute(); temp[0] += 30; return temp; } } }