装饰者模式:动态的给一个对象,增加一些额外的功能。
这张UML图中可以看出,Component是一个抽象出来的组件或接口,有了两个类(ConcreteComponent和Decorator)实现了它。
这里可以看出Decorator可以产生 好几个子类,这些子类的创建 不会影响到原来的ConcreteComponent类。耦合性降低了。
1、组件(Component)角色:就是装饰器模式中公共方法的抽象类或接口,在装饰器模式结构图的顶层。
2、具体组件(ConcreateComponent)角色:是转换器模式中具体的被装饰的类,实现组件角色的类。
3、装饰(Decorator)角色:装饰器模式中的核心对象,所有具体装饰器对象的父类,完成装饰器的部分职能。在上面的例子中Decorator类和这里的对应。该类可以只做一些简单的包裹被装饰的对象,也可以还包含对Component中方法的实现……他有一个鲜明的特点:继承至Component,同时包含一个Component作为其成员变量。装饰器模式动机中的动态地增加功能是在这里实现的。
4、装饰子类角色:ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰器对象,他们完成具体的装饰功能。装饰功能的实现是通过调用被装饰对象对应的方法,加上装饰对象自身的方法。这是装饰器模式动机中的添加额外功能的关键。
代码using System; namespace DoFactory.GangOfFour.Decorator.Structural { /// <summary> /// MainApp startup class for Structural /// Decorator Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Create ConcreteComponent and two Decorators ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); // Link decorators d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Component' abstract class /// </summary> abstract class Component { public abstract void Operation(); } /// <summary> /// The 'ConcreteComponent' class /// </summary> class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("ConcreteComponent.Operation()"); } } /// <summary> /// The 'Decorator' abstract class /// </summary> abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } /// <summary> /// The 'ConcreteDecoratorA' class /// </summary> class ConcreteDecoratorA : Decorator { public override void Operation() { base.Operation(); Console.WriteLine("ConcreteDecoratorA.Operation()"); } } /// <summary> /// The 'ConcreteDecoratorB' class /// </summary> class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("ConcreteDecoratorB.Operation()"); } void AddedBehavior() { } } }
Output
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()
代码using System; using System.Collections.Generic; namespace DoFactory.GangOfFour.Decorator.RealWorld { /// <summary> /// MainApp startup class for Real-World /// Decorator Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Create book Book book = new Book("Worley", "Inside ASP.NET", 10); book.Display(); // Create video Video video = new Video("Spielberg", "Jaws", 23, 92); video.Display(); // Make video borrowable, then borrow and display Console.WriteLine("\nMaking video borrowable:"); Borrowable borrowvideo = new Borrowable(video); borrowvideo.BorrowItem("Customer #1"); borrowvideo.BorrowItem("Customer #2"); borrowvideo.Display(); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Component' abstract class /// </summary> abstract class LibraryItem { private int _numCopies; // Property public int NumCopies { get { return _numCopies; } set { _numCopies = value; } } public abstract void Display(); } /// <summary> /// The 'ConcreteComponent' class /// </summary> class Book : LibraryItem { private string _author; private string _title; // Constructor public Book(string author, string title, int numCopies) { this._author = author; this._title = title; this.NumCopies = numCopies; } public override void Display() { Console.WriteLine("\nBook ------ "); Console.WriteLine(" Author: {0}", _author); Console.WriteLine(" Title: {0}", _title); Console.WriteLine(" # Copies: {0}", NumCopies); } } /// <summary> /// The 'ConcreteComponent' class /// </summary> class Video : LibraryItem { private string _director; private string _title; private int _playTime; // Constructor 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("\nVideo ----- "); Console.WriteLine(" Director: {0}", _director); Console.WriteLine(" Title: {0}", _title); Console.WriteLine(" # Copies: {0}", NumCopies); Console.WriteLine(" Playtime: {0}\n", _playTime); } } /// <summary> /// The 'Decorator' abstract class /// </summary> abstract class Decorator : LibraryItem { protected LibraryItem libraryItem; // Constructor public Decorator(LibraryItem libraryItem) { this.libraryItem = libraryItem; } public override void Display() { libraryItem.Display(); } } /// <summary> /// The 'ConcreteDecorator' class /// </summary> class Borrowable : Decorator { protected List<string> borrowers = new List<string>(); // Constructor 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(" borrower: " + borrower); } } } }
Output
Book ------
Author: Worley
Title: Inside ASP.NET
# Copies: 10
Video -----
Director: Spielberg
Title: Jaws
# Copies: 23
Playtime: 92
Making video borrowable:
Video -----
Director: Spielberg
Title: Jaws
# Copies: 21
Playtime: 92
borrower: Customer #1
borrower: Customer #2