一、 装饰(Decorator)模式
装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
二、 装饰模式的结构
- 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任
/// <summary> /// 装饰(Decorator)模式 /// 装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。 /// 装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。 /// </summary> class Program { static void Main(string[] args) { // 创建的书和视频和显示 Book book = new Book("巴金", "家", 10); Video video = new Video("不详","扫毒", 23, 120); book.Display(); video.Display(); // 查看图书,然后借阅 Console.WriteLine(" 查看图书,然后借阅:"); Borrowable borrowvideo = new Borrowable(book); borrowvideo.BorrowItem("小三"); borrowvideo.BorrowItem("小四"); borrowvideo.Display(); Console.ReadLine(); } } /// <summary> /// 抽象构件(Component)角色 /// </summary> public abstract class LibraryItem { // 字段 private int numCopies; // 属性 public int NumCopies { get { return numCopies; } set { numCopies = value; } } // 方法 public abstract void Display(); } /// <summary> /// 具体构件(Concrete Component)角色 /// </summary> public class Book : LibraryItem { // 字段 private string author; private string title; // 构造函数 public Book(string author, string title, int numCopies) { this.author = author; this.title = title; this.NumCopies = numCopies; } // 函数 public override void Display() { Console.WriteLine(" 书(Book) ------ "); Console.WriteLine(" 作者: {0}", author); Console.WriteLine(" 书名: {0}", title); Console.WriteLine(" # 副本: {0}", NumCopies); } } /// <summary> /// 具体构件(Concrete Component)角色 /// </summary> public class Video : LibraryItem { // 字段 private string director; private string title; private int playTime; // 构造函数 public Video(string director, string title,int numCopies, int playTime) { this.director = director; this.title = title; this.NumCopies = numCopies; this.playTime = playTime; } // 方法 public override void Display() { Console.WriteLine(" 视频(Video) ----- "); Console.WriteLine(" 导演: {0}", director); Console.WriteLine(" 片名: {0}", title); Console.WriteLine(" # 副本: {0}", NumCopies); Console.WriteLine(" 时长: {0} 分钟", playTime); } } /// <summary> /// 装饰(Decorator)角色 /// </summary> public abstract class Decorator : LibraryItem { // 字段 protected LibraryItem libraryItem; // 构造函数 public Decorator(LibraryItem libraryItem) { this.libraryItem = libraryItem; } // 方法 public override void Display() { libraryItem.Display(); } } /// <summary> /// 具体装饰(Concrete Decorator)角色 /// </summary> public class Borrowable : Decorator { // 字段 protected ArrayList borrowers = new ArrayList(); // 构造函数 public Borrowable(LibraryItem libraryItem) : base(libraryItem) { } // 方法 public void BorrowItem(string name) { borrowers.Add(name); libraryItem.NumCopies--; } public void ReturnItem(string name) { borrowers.Remove(name); libraryItem.NumCopies++; } public override void Display() { base.Display(); foreach (string borrower in borrowers) Console.WriteLine(" 借阅人: {0}", borrower); } }
三、 装饰模式应当在什么情况下使用
在以下情况下应当使用装饰模式:
- 需要扩展一个类的功能,或给一个类增加附加责任。
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
4. 如果只有一个 具体构件(Concrete Component)角色 的时候 可以不要抽象构件(Component)角色
//创建ConcreteComponent和两个修饰符 ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); // 链接修饰符 d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); /// <summary> /// 抽象构件(Component)角色 /// </summary> public abstract class Component { // 方法 public abstract void Operation(); } // "具体构建" public class ConcreteComponent : Component { // 方法 public override void Operation() { Console.WriteLine("具体对象的操作"); } } // 装饰(Decorator)角色 public abstract class Decorators : Component { // 字段 protected Component component; // 方法 public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) component.Operation(); } } // "具体装饰A" class ConcreteDecoratorA : Decorators { private string addedState; public override void Operation() { base.Operation(); addedState = "new state"; Console.WriteLine("具体装饰对象A的操作"); } } // "具体装饰B" public class ConcreteDecoratorB : Decorators { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("具体装饰对象B的操作"); } void AddedBehavior() { } }
Console.WriteLine(" =========搭配衣服============= "); Person xc = new Person("鸟人-安德森"); TShirts tx = new TShirts(); BigTrouser kk = new BigTrouser(); tx.Decorate(xc); kk.Decorate(tx); kk.Show(); /// <summary> /// 如果只有一个 具体构件(Concrete Component)角色 的时候 /// 可以不要抽象构件(Component)角色 /// </summary> public class Person { public Person() { } private string name; public Person(string name) { this.name = name; } public virtual void Show() { Console.WriteLine("装扮的{0}", name); } } ///装饰(Decorator)角色 public class Finery : Person { protected Person component; //打扮 public void Decorate(Person component) { this.component = component; } public override void Show() { if (component != null) component.Show(); } } /// <summary> /// 具体装饰 /// </summary> public class TShirts : Finery { public override void Show() { Console.WriteLine("大T恤"); base.Show(); } } /// <summary> /// 具体装饰 /// </summary> public class BigTrouser : Finery { public override void Show() { Console.WriteLine("大垮裤"); base.Show(); } }