模式定义
装饰模式(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);
}
}
}