初尝Decorator 模式
一副画,可以挂在墙上。但通常,它们都会被装入相框之后,再被挂起来。据说如此一来,可以保证画面持久如新。如果这样一幅画的名字叫做《蒙娜丽莎的微笑》,那么在相框之外,可能还隔着一道水晶墙。据说如此一来,不但画面可以持久如新,还能保证名画本身不受到“意外”的损伤。在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质(编译固定),使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。为什么不使用前面蒙娜丽莎的智慧来解决“子类复子类,子类何其多”的困境呢?这就是我今天刚学的Decorator 模式。
意图
动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。
结构图
假设要对现有文档进行功能的扩充,比如加密、压缩等。即可使用Decorator 模式进行,下面便是代码了:
using System;
namespace Decorator
{
abstract class Document {
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
//public abstract void Open();
//public abstract void Close();
public abstract void Save();
}
class EncryptDecorator : Document {
private Document doc;
public EncryptDecorator(Document doc) {
this.doc = doc;
base.Name = doc.Name;
}
private void Encrypt() {
Console.WriteLine("{0} has been Encypted!",doc.Name);
}
//先加密,然后保存
public override void Save() {
this.Encrypt();
doc.Save();
}
}
class ZIPDecorator : Document {
private Document doc;
public ZIPDecorator(Document doc) {
this.doc = doc;
base.Name = doc.Name;
}
private void ZIP() {
Console.WriteLine("{0} has been Ziped!",doc.Name);
}
//先保存,然后压缩
public override void Save() {
doc.Save();
this.ZIP();
}
}
class PDF : Document{
public PDF(){
base.Name = "PDF";
}
public override void Save(){
Console.WriteLine("{0} has been Saved!", base.Name);
}
}
class TXT : Document {
public TXT() {
base.Name = "TXT";
}
public override void Save() {
Console.WriteLine("{0} has been Saved!",base.Name);
}
}
class Program
{
static void Main(string[] args)
{
Document doc = new TXT();
Console.WriteLine("普通的TXT 文档:");
doc.Save();
Console.WriteLine("-------------------------------");
EncryptDecorator doc1 = new EncryptDecorator(doc);
Console.WriteLine("仅扩展了加密功能的TXT文档:");
doc1.Save();
Console.WriteLine("-------------------------------");
//仅扩展了压缩功能
ZIPDecorator doc2 = new ZIPDecorator(doc);
Console.WriteLine("仅扩展了压缩功能的TXT文档:");
doc2.Save();
Console.WriteLine("-------------------------------");
//既扩展了加密功能,又扩展了压缩功能
ZIPDecorator doc3 = new ZIPDecorator(doc1);
Console.WriteLine("既扩展了加密功能,又扩展了压缩功能的TXT文档:");
doc3.Save();
}
}
}
运行截图:
总结:
- Decorator 是一个非常有用的模式,经常用来对一些现有类进行包装。通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。
- Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。
- Decortor模式并非解决“多子类衍生的多继承”问题,Decorator模式的应用要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。
另外,Decortor 和Bridge 模式之间是有着一定区别的:
Decorator是对已有功能的增强, 装饰类都是围绕被装饰类已有的功能而展开的, 无论装饰类怎么变, 它都必须围绕被装饰类来变化(或者是围绕二者公共的接口来变化), 因为对于客户程序来说, 调用装饰前后的对象应该是一致的. 而Bridge模式是将行为从被桥接对象(抽象类)中分离出去, 完全放到实现类中去实现, 行为实现将更少的受到被桥接对象的限制. 所以如果这种约束是必要的,就可以采用Decorator模式, 反之则可以采用Bridge模式 。


近期评论