Q?Q?装饰对象和真实对象有相同的接口。这样客L对象可以以和真实对象相同的方式和装饰对象交互?br />
Q?Q?装饰对象包含一个真实对象的索引QreferenceQ?br />
Q?Q?装饰对象接受所有的来自客户端的h。它把这些请求{发给真实的对象?br />
Q?Q?装饰对象可以在{发这些请求以前或以后增加一些附加功能。这样就保了在q行Ӟ不用修改l定对象的结构就可以在外部增加附加的功能。在面向对象的设计中Q通常是通过l承来实现对l定cȝ功能扩展?br />
装饰模式 l承
用来扩展特定对象的功?nbsp; 用来扩展一cd象的功能
不需要子c?nbsp; 需要子c?br />
动态地 静态地
q行时分配职?nbsp; ~译时分z职?br />
防止׃子类而导致的复杂和?nbsp; D很多子类产生Q在一些场合,报漏cȝ层次
更多的灵zL?nbsp; ~Z灉|?br />
让我们重新返回我们在工厂Ҏ和单例模式log实用工具上,我们的模式主要由Logger 接口和两个它的实现类??FileLogger和ConsoleLogger??分别把信息出力到一个文件和屏幕中。另外,q有包括工厂Ҏ的LoggerFactorycR?br />
LoggerFactory没有出现在下图中Q主要是因ؓ它和现在讨论的例子没有直接联pR?br />
让我们想象一些客L需要以出Logger Utility现在所提供的新的方式出力信息,客户端需要下面两U特征;
Q?Q?把出力的信息传唤为HTML文档
Q?Q?对出力信息进行逻辑转化的简单加密,在面向对象的设计中,不改变现存的cȝ代码Q可以应用承来增加新的功能。例如,子类化现在的c重载它的方法来增加所需要的新功能?/span>
应用l承Q我们要子类化FileLogger和ConsoleLoggercL增加新的功能Q会有下面的一l新的子c:
子类 父类 功能
HTMLFileLogger FileLogger 转化出力信息为HTML文Qƈ存入一个Log文g
HTMLConsLogger ConsoleLogger 转化出力信息为HTML文Qƈ昄在屏q上
EncFileLogger FileLogger 加密出力信息Qƈ存入一个Log文g
EncConsLogger ConsoleLogger 加密出力信息Qƈ昄在屏q上
从类囑֏以看刎ͼZ实现新的功能加入了一l新的子cR如果我们还有其他的LoggercdQ例如:DBLogger出力信息到数据库中)Q这样会有更多子cR当一个新的特性需要被加入Q子cȝ数量会有成倍数的增长,同时我们会有一个庞大的cdơ?br />
装饰模式使我们从q种情景中解脱出来,装饰模式推荐通过对象的合成而不是承来包装一个对象扩展它的功能?br />
应用装饰模式Q让我们为Logger Utility定义一个有下列特征的默认根装饰cLoggerDecoratorQ?/span>
Q?Q?LoggerDecorator包括一个Logger实例的引用。这个引用指向它包含的Logger对象?br /> Q?Q?LoggerDecorator实现Logger借口、提供LogҎ的基本的默认实现Q他只是单的转发调用l它包含的Logger 对象。每一个LoggerDecorator子类保证定义logҎ?/span>
Listing 19.1: LoggerDecorator Class
每一个logger的装饰定义logҎ使很重要的,因ؓ装饰对象必须提供和它包装的对象相同的借口。当客户端创Z个装饰类的实例,客户端以与装饰类交互方式和客L与拥有相同接口原对象的交互方式是一致的?br /> 让我们定义LoggerDecorator的两个子c,HTMLLogger和EncryptLogger?#p# 具体的Logger 装饰c?/strong>
HTMLLogger重蝲了logҎ的默认实现。在logҎ中,装饰cL出力信息转化为HTML文档Qƈ且发送给可以出力的Logger实例?br />
Listing 19.2: HTMLLogger Class
与HTMLLogger怼QEncryptLogger重蝲了logҎQ在logҎ中,EncryptLogger通过单的字W位|向双{UM位实C加密逻辑Qƈ且发送给可以出力的Logger实例?br />
Listing 19.3: EncryptLogger Class
Q?Q?使用LoggerFactory工厂Ҏ创徏一个合适的Logger实例QFileLogger/ConsoleLoggerQ?br /> Q?Q?把第一步中创徏的Logger实例作ؓ参数转递给新创建的合适的LoggerDecorator实例的构造函数?br /> Q?Q?调用LoggerDecorator实例上的ҎQ?/span>
Listing 19.4: Client DecoratorClient Class
在Logging Utility实例中,应用装饰模式Ҏ使用l承不会因ؓcdơ的增长而导致大量的子类Q我们还有另外的LoggercdQDBLogger??出力信息到数据库中。ؓ了将信息转化HTML格式或在出力到数据库以前对信息进行加密,客户端只需遵从上面提到的步骤,因ؓDBLogger是一ULoggercdQ它可以作ؓ构造函数的参数传递给HTMLLogger或EncryptLogger中Q何一个类?br />
从例子中可以看到QLoggerDecorator实例包含了一个Loggercd了对象实例,在{发请求给Logger对象实例以前或以后,增加新的功能。因为LoggerDecoratorcdCLogger接口QLoggerDecorator实例或它的Q何一个子c都可以作ؓ一个Loggercd。因此LoggerDecortator包含它的M子类的一个实例,q且请求{发给?。一般的一个装饰对象可以包含另一个装饰对象,q且可以向它转发h。通过q种方式Q新的装饰类Q新的功能可以通过包装现存的装饰类来实现?/span>