目录
- 定义
- UML
- 参与者
- 示例
定义:
装饰者模式:动态的给一个对象,增加一些额外的功能。
UML:
这张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