Design patterns 设计图案装饰

Design patterns 设计图案装饰,design-patterns,decorator,Design Patterns,Decorator,我第一次在IO类中看到装饰器模式。现在,我正在看一门关于pluralsight、封装和实体的课程,课程中讨论了装饰图案的另一种用法。这是类图 MessageStore | <interface> IStoreReader

我第一次在IO类中看到装饰器模式。现在,我正在看一门关于pluralsight、封装和实体的课程,课程中讨论了装饰图案的另一种用法。这是类图

                            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(...)))