装饰模式:(Decorator),动态地给一个对象添加一些额外的职责,比单纯的继承更为灵活合理,应用场合比如java的System.IO各种输出就是通过装饰模式来实现的,还有一些日志类,动态的添加日志记录的功能,将耦合度降到最低。这里的基本内容参照大话设计模式的,但是这一节将的并不好,再额外做些补充,供自己和园友们做备忘录用。
Componet 是定义一个对象接口,可以给这些对象动态的添加职责,
ConcreteComponent是定义了一个具体的对象, 也可以给这些对象添加一些职责。
Decorator,装饰抽象类,继承了Component,从外类来扩展Component的功能,
但对于Component来说,是无需要知道Decorator类的存在。
至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
UML画的不熟练,错误地方望大家指出
1.定义抽象接口
abstract class Component
{
public abstract void Operation();
}
2.定义一个基础的实现类
class ConcreteComponent:Component
{
public override void Operation()
{
Console.WriteLine("具体的对象操作");
}
}
3.定义装饰调度类
abstract class Decorator:Component
{
protected Component component;
/// <summary>
/// 设置定义的接口
/// </summary>
/// <param name="component"></param>
public void SetComponent(Component component)
{
this.component = component;
}
/// <summary>
/// 重写Operation,实际上执行的是Component的Operation()
/// </summary>
public override void Operation()
{
if(component!=null)
{
component.Operation();
}
}
}
4.定义具体装饰类A
class ConcreteDecoratorA:Decorator
{
/// <summary>
/// 当前类的私有属性,区别于其他类
/// </summary>
private void AddBehavior()
{
Console.WriteLine("CocreteDecoratorA 的私有方法");
}
public override void Operation()
{
/*首先运行了原Component的Operation()
再执行了当前类的功能,相当于对原Component进行了装饰
*/
AddBehavior();
Console.WriteLine("具体装饰对象A的操作");
base.Operation();
}
}
5.定义具体装饰类B
class ConcreteDecoratorB : Decorator
{
/// <summary>
/// 当前类的私有方法,区别于其他类
/// </summary>
private void AddBehavior()
{
Console.WriteLine("具体对象B的装饰");
}
public override void Operation()
{
/*首先运行了原Component的Operation()
再执行了当前类的功能,相当于对原Component进行了装饰
*/
AddBehavior();
Console.WriteLine("具体装饰对象B的操作");
base.Operation();
}
}
客户端调用:
/// <summary>
/// 装饰模式
/// </summary>
static void TestDecorator()
{
//装饰的方法:首先用ConcreteComponent实例化对象c
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA cdA = new ConcreteDecoratorA();
ConcreteDecoratorB cdB = new ConcreteDecoratorB();
//然后用ConcreteDecoratorA 的实例化对象cdA来包装c
cdA.SetComponent(c);
//再用ConcreteDecoratorB的实例化对象cdB来包装cdA
cdB.SetComponent(cdA);
//最终执行cdB的Operation()
cdB.Operation();
Console.Read();
}
小结:装饰类的功能很强大,但是灵活运用起来不简单,需要仔细体会面向对象的设计,以下是贴出在网上搜集的一个比较好的例子,比大话设计模式的里面 的那个例子更严谨。
namespace DesignPatternLab.DecoratoryPackage
{
/// <summary>
/// 首先,我们需要一个手机的接口或者是抽象类,我这里就用抽象类来实现,代码如下
/// </summary>
public abstract class AbstractCellPhone
{
public abstract string CallNumber();
public abstract string SendMessage();
}
//然后,我再来实现Nokia和Moto的手机类
public class NokiaPhone : AbstractCellPhone
{
public override string CallNumber()
{
return "NokiaPhone call sombody";
}
public override string SendMessage()
{
return "NokiaPhone send a message to somebody";
}
}
//然后,我再来实现Nokia和Moto的手机类
public class MotoPhone : AbstractCellPhone
{
public override string CallNumber()
{
return "MotoPhone call sombody";
}
public override string SendMessage()
{
return "MotoPhone send a message to somebody";
}
}
//接下来我需要一个Decorator接口或者抽象类,实现代码如下
public abstract class CellDecorator : AbstractCellPhone
{
AbstractCellPhone _phone;
public CellDecorator(AbstractCellPhone phone)
{
_phone = phone;
}
public override string CallNumber()
{
return _phone.CallNumber();
}
public override string SendMessage()
{
return _phone.SendMessage();
}
}
/// <summary>
/// 这个Decorator即继承了AbstractCellPhone,
/// 又包含了一个私有的AbstractCellPhone的对象。
/// 这样做的意义是:Decorator类又使用了另外一个Component类。
/// 我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,
/// 且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,
/// 它们要继承自Decorator,代码如下
/// </summary>
public class DecoratorGPS : CellDecorator
{
public DecoratorGPS(AbstractCellPhone phone):base(phone)
{ }
public override string CallNumber()
{
return base.CallNumber() + " with GPS";
}
public override string SendMessage()
{
return base.SendMessage() + " with GPS";
}
}
public class DecoratorBlueTooth : CellDecorator
{
public DecoratorBlueTooth(AbstractCellPhone phone)
: base(phone)
{ }
public override string CallNumber()
{
return base.CallNumber() + " with BlueTooth";
}
public override string SendMessage()
{
return base.SendMessage() + " with BlueTooth";
}
}
}
客户端调用:
/// <summary>
/// 装饰模式案例
/// </summary>
static void TestDecoratorCellPhone()
{
AbstractCellPhone phone = new NokiaPhone();
Console.WriteLine(phone.CallNumber());
Console.WriteLine(phone.SendMessage());
DecoratorGPS gps = new DecoratorGPS(phone); //add GSP
Console.WriteLine(gps.CallNumber());
Console.WriteLine(gps.SendMessage());
DecoratorBlueTooth bluetooth = new DecoratorBlueTooth(gps); //add GSP and bluetooth
Console.WriteLine(bluetooth.CallNumber());
Console.WriteLine(bluetooth.SendMessage());
Console.Read();
}