模式定义
装饰模式(Decorator Pattern)
动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。
UML类图
- 抽象构件(Component) 需要被装饰的类,定义了对象的接口,装饰器可以给它增加额外的职责(方法)
- 具体构建(Concrete Component)实现了接口,装饰器可以给它增加额外的职责(方法)
- 抽象装饰类(Decorator) 抽象构件的子类,并有关联抽象构件类,方便调用构件方法(确保在原有方法上修改或添加职能)用于给具体构件增加职责,但是具体职责在其子类中实现
具体装饰类(Concrete Decorator)
代码结果
public static class DecoratorApp { public static void Run() { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); Console.ReadKey(); } } public abstract class Componet { public abstract void Operation(); } public class ConcreteComponent : Componet { public override void Operation() { Console.WriteLine("Concrete Component.Operation()"); } } public abstract class Decorator : Componet { protected Componet component; public void SetComponent(Componet component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } public class ConcreteDecoratorA : Decorator { public override void Operation() { base.Operation(); Console.WriteLine("Concrete DecoratorA.Operation()"); } } public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); Console.WriteLine("Concrete DecoratorB.Operation()"); AddedBehavior(); } void AddedBehavior() { Console.WriteLine("add behavior"); } }
情景模式
这里以图书馆借阅为例,图书馆可借阅的有书和光盘,将书和光盘抽象为可借阅的东西。通过装饰类添加借阅功能。
public static class RealWorldDecoratorApp { public static void Run() { Book book = new Book() { Author = "Worley", Title = "Inside ASP.NET", NumCopies = 10 }; book.Display(); Video video = new Video() { Director = "Spielberg", Title = "Jaws", NumCopies = 23, PlayTime = 92 }; video.Display(); Console.WriteLine("\nMaking video borrowable:"); Borrowable borrowvideo = new Borrowable(video); borrowvideo.BorrowItem("Customer #1"); borrowvideo.BorrowItem("Customer #2"); borrowvideo.Display(); } } public abstract class LibraryItem { public int NumCopies { get; set; } public abstract void Display(); } public class Book : LibraryItem { public string Author { get; set; } public string Title { get; set; } public override void Display() { Console.WriteLine("\nBook-----"); Console.WriteLine("Author:{0}", this.Author); Console.WriteLine("Title:{0}", this.Title); Console.WriteLine("# Copies:{0}", NumCopies); } } public class Video : LibraryItem { public string Director { get; set; } public string Title { get; set; } public int PlayTime { get; set; } public override void Display() { Console.WriteLine("\nVideo-----"); Console.WriteLine("Director:{0}", this.Director); Console.WriteLine("Title:{0}", this.Title); Console.WriteLine("# Copies:{0}", NumCopies); Console.WriteLine("Playtime:{0}", this.PlayTime); } } public abstract class Decorator : LibraryItem { protected LibraryItem libraryItem; public Decorator(LibraryItem libraryItem) { this.libraryItem = libraryItem; } public override void Display() { libraryItem.Display(); } } public class Borrowable : Decorator { protected List<string> borrowers = new List<string>(); 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); } } }