Design patterns 设计图案装饰
我第一次在IO类中看到装饰器模式。现在,我正在看一门关于pluralsight、封装和实体的课程,课程中讨论了装饰图案的另一种用法。这是类图Design patterns 设计图案装饰,design-patterns,decorator,Design Patterns,Decorator,我第一次在IO类中看到装饰器模式。现在,我正在看一门关于pluralsight、封装和实体的课程,课程中讨论了装饰图案的另一种用法。这是类图 MessageStore | <interface> IStoreReader
MessageStore
|
<interface>
IStoreReader
|
---------------------------------------------------------
| | |
StoreLogger StoreCache FileStore
IStoreReader的唯一方法是read(int-id)
代码如下所示:
StoreLogger :
public List<String> read(int id){
log.information("Reading ...");
return this.storeReader.read(id);
log.information("Done reading ...");
}
StoreCache :
public List<String> read(id){
List<String> result = this.cache.find(id);
if(result.isEmpty()){
return this.storeReader.read(id);
}
return result;
}
FileStore:
public List<String> read(id){
//implementation
}
StoreLogger:
公共列表读取(int id){
日志信息(“阅读…”);
返回此.storeReader.read(id);
日志信息(“完成阅读…”);
}
StoreCache:
已读取公共列表(id){
列表结果=this.cache.find(id);
if(result.isEmpty()){
返回此.storeReader.read(id);
}
返回结果;
}
文件存储:
已读取公共列表(id){
//实施
}
由于MessageStore只与一个IStoreReader交互,因此只传递了StoreLogger的实例,这就是一直困扰我的问题。如果将这3个类传递给MessageStore(因为我相信这在某种程度上是一个服务类),并且可以用3个更具体的接口替换唯一的接口,那么解决方案不是更好吗?可读性是本设计的另一个关注点
另外,当我第一次看到decorator模式是如何被使用的时候,我注意到它的目的是为传递的模式增加新的价值;正如在IO中所观察到的,如InputStream、BufferedInputStream等
请帮助我了解这一点 Decorator是一种非常强大的设计模式,它包装了现有的类,并在其上添加了更多功能,例如在您的案例中的日志记录和缓存。界面的用户不需要知道正在使用哪个特定的实现 如果将这3个类传递给 MessageStore(因为我认为这是一个服务类?) 唯一的接口可以替换为3个更具体的接口 不,因为请考虑如果需要使用配置禁用缓存,您会怎么做。
MessageStore
是否需要知道缓存已禁用?如果提供给MessageStore
的对象不缓存,则效果会更好。这就是多态性和装饰器的威力
使用缓存:
IStoreReader reader = new StoreCache(new StoreLogger(new FileStore("file")));
没有缓存:
IStoreReader reader = new StoreLogger(new FileStore("file"));
因此,使用decorator时发生的唯一变化是如何创建对象并将它们连接在一起。我认为这是一个更好的设计,因为只需要将单个对象传递到MessageStore
就日志记录而言,也可以使用AOP完成,但这是一个很好的示例,可以开始使用decorator
如果您还有任何疑问,请告诉我。装饰者模式的全部要点是将“动作”的动态组合链接在一起。对于您的示例,让我们看看它对您有何好处(与
MessageStore
相比,它采用了3个特定接口,而不是1个更抽象的接口)
考虑一下,如果第一个存储失败,您希望提供一些“备份”存储。然后您可以轻松创建StoreBackup
,使用以下read
功能获取两个istoreead
实例:
public List<String> read(id){
List<String> result = this.mainStore.read(id);
if(result.isEmpty()){
result = this.backupStore.read(id);
}
return result;
}
当然,这也可以通过修改的MessageStore
来实现,但需要您更改其代码(引入新的控制变量、方法等),而不仅仅是更改客户端代码
public List<String> read(id){
List<String> result = this.mainStore.read(id);
if(result.isEmpty()){
result = this.backupStore.read(id);
}
return result;
}
new StoreCache(new StoreLogger(new FileStore(...)))