结构型模式--代理模式&&适配器模式&&装饰器模式

2020-03-13  本文已影响0人  kirito_song

算是读书笔记吧

极客时间--设计模式之美


代理模式和装饰器模式的在实现上相同,所以放在一起看。

以代理模式为例

// 代理模式的代码结构(下面的接口也可以替换成抽象类)
public interface IA {
  void f();
}
public class A impelements IA {
  public void f() { //... }
}
public class AProxy impements IA {
  private IA a;
  public AProxy(IA a) {
    this.a = a;
  }
  
  public void f() {
    // 新添加的代理逻辑
    a.f();
    // 新添加的代理逻辑
  }
}

private void demo() {
  IA a = AProxy(A.new())
  a.f()
}

二者的相似性

主要解决继承关系过于复杂的问题,借助面向接口的编程思想,通过组合来替代继承。

在不改变原始类(或叫被代理类)代码的情况下,由新的类和原始类需要实现相同的接口。


二者的区别性

二者的区别体现在想要对原始类附加的功能

代理模式

将功能直接转交给代理类进行实现。

偏重业务无关,高度抽象,和稳定性较高的场景。
由原始类指定代理类,对业务方隐藏代理类的存在。

比如对数据访问功能添加日志,缓存。

装饰器模式

给原始类添加增强功能。

偏重业务相关,定制化诉求高,改动较频繁的场景。
由业务方指定装饰类,依赖业务方的具体实现。

比如业务级别上对日志增加字段、数据的加工整理。

代理模式主要目的是控制访问,而非加强功能。这是它跟装饰器模式最大的不同


适配器模式

适配器模式与代理和装饰器模式一样,也是基于面向接口编程的特性,通过接口对不同的类进行统一约束。

这里的统一,体现在:


// 使用适配器模式进行改造
public interface ISensitiveWordsFilter { // 统一接口定义
  String filter(String text);
}

// 扩展性更好,更加符合开闭原则,如果添加一个新的敏感词过滤系统,
// 这个类完全不需要改动;而且基于接口而非实现编程,代码的可测试性更好。
public class RiskManagement { 
  private List<ISensitiveWordsFilter> filters = new ArrayList<>();
 
  public void addSensitiveWordsFilter(ISensitiveWordsFilter filter) {
    filters.add(filter);
  }
  
  public String filterSensitiveWords(String text) {
    String maskedText = text;
    for (ISensitiveWordsFilter filter : filters) {  //这里每个filter的filter方法内部,包裹着真实实现
      maskedText = filter.filter(maskedText);
    }
    return maskedText;
  }
}

当然,也有为了版本兼容而使用的适配器模式。将适配器实现的细节,转接给另一个类进行实现

/**
 * Returns an enumeration over the specified collection.  This provides
 * interoperability with legacy APIs that require an enumeration
 * as input.
 *
 * @param  <T> the class of the objects in the collection
 * @param c the collection for which an enumeration is to be returned.
 * @return an enumeration over the specified collection.
 * @see Enumeration
 */
public static <T> Enumeration<T> enumeration(final Collection<T> c) {
  return new Enumeration<T>() {
    private final Iterator<T> i = c.iterator();

    public boolean hasMoreElements() {
      return i.hasNext();
    }

    public T nextElement() {
      return i.next();
    }
  };
}

适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
一般来说,适配器模式可以看作一种“补偿模式”,用来补救设计上的缺陷。应用这种模式算是“无奈之举”,如果在设计初期,我们就能协调规避接口不兼容的问题,那这种模式就没有应用的机会了。

上一篇下一篇

猜你喜欢

热点阅读