接口解耦

例子摘自 Thingking in java8第10章接口之完全解耦一節.

https://lingcoder.github.io/OnJava8/#/book/10-Interfaces?id=%e5%ae%8c%e5%85%a8%e8%a7%a3%e8%80%a6

剛開始Processor是個父類,

class Processor {
  public String name() {
    return getClass().getSimpleName();
  }

  public Object process(Object input) {
    return input;
  }
}

下面一堆子類繼承他,然後將聲明的父類傳到Applicator類的方法中.

public class Applicator {
  public static void apply(Processor p, Object s) {
    System.out.println("Using Processor " + p.name());
    System.out.println(p.process(s));
  }
}

 

這樣做Processor就只能處理某一種類型的對象.沒有解耦.

現在有類似方法的類Filter出現了,想要複用Applicator類代碼.但是因爲apply方法接收的是Processor類所以沒法複用.

class Filter {

  public String name() {
    return getClass().getSimpleName();
  }

  public Waveform process(Waveform input) {
    return input;
  }
}

 

如果Processor是一個接口,apply方法接收一個接口參數,那麼就不會跟具體的類綁定,實現瞭解耦.

interface Processor {

  default String name() {
    return getClass().getSimpleName();
  }

  Object process(Object input);
}

 

Applicator改寫成接收接口參數的形式:

Applicator還是個類,它裏面保有固定的具體的方法代碼.

雖然apply方法裏參數是接口形式的,但實際要傳實現類進去

class Applicator {
                            //現在Processor是接口
  public static void apply(Processor p, Object s) {
    System.out.println("Using Processor " + p.name());
    System.out.println(p.process(s));
  }
}

現在的Processor是一個抽象的籠統的”處理器”角色,

可以根據不同任務創建不同的,特定方向的”子處理器”角色.

子類型接口繼承父類型接口(接口不能繼承類,否則會獲得父類的構造方法,而接口只允許有靜態變量,默認方法或抽象方法)

interface StringProcessor extends Processor {
  @Override
  String process(Object input); // [1]
  String S = "If she weighs the same as a duck, she's made of wood"; // [2]
}

 

然後根據子接口創建更具體的實現類Upcase來處理任務.

class Upcase implements StringProcessor {
  // 返回協變類型
  @Override
  public String process(Object input) {
    return ((String) input).toUpperCase();
  }
}

 

現在Applicator可以工作了:

public class test{
  static void main(String[] args) { // [3]
    Applicator.apply(new Upcase(), S);
    Applicator.apply(new Downcase(), S);
    Applicator.apply(new Splitter(), S);
  }
}

 

但是現實情況是很多類是已有的或別人創建的,只能拿來用但是不能修改.

所以上面的情況可以再改成適配器設計模式.適配器允許代碼接受已有的接口產生需要的接口.

 

這裏有一個Filter類的子類:

public class HighPass extends Filter {
  double cutoff;

  public HighPass(double cutoff) {
    this.cutoff = cutoff;
  }

  @Override
  public Waveform process(Waveform input) {
    return input;
  }
}

 

改成下面這個樣子:

public class FilterProcessor {
  public static void main(String[] args) {
    Waveform w = new Waveform();
    Applicator.apply(new FilterAdapter(new LowPass(1.0)), w);
    Applicator.apply(new FilterAdapter(new HighPass(2.0)), w);
    Applicator.apply(new FilterAdapter(new BandPass(3.0, 4.0)), w);
  }
}
public class LowPass extends Filter {
  double cutoff;

  public LowPass(double cutoff) {
    this.cutoff = cutoff;
  }

  @Override
  public Waveform process(Waveform input) {
    return input; // Dummy processing 啞處理
  }
}

 

在StringProcessor的例子裏,Upcase類裏的方法是String自帶的.無需指定其他對象.

但是Waveform的例子裏,處理波的對象是Filter,需要從外面引入.

怎麼調和這種差異呢?

 

apply方法的參數已經定義好了,一個處理者(接口),一個被處理者.

解決辦法是:對於waveform例子,引入適配器adapter這一對象去引入Filter.適配器實現了接口.可以滿足apply的參數要求.

 

簡單來說,stringProcessor的例子裏,只需要2個參數,處理者和被處理對象,調的是對象的方法.

wave的例子裏調的是處理者的方法.

 

apply方法的第一個參數就有了不一致的情形.也就是Processor裏的process方法是有區別的.

stringProcessor例子裏的process方法只要被處理着本身一個參數,

wave例子裏需要引入處理者,

但是process方法是固定的.不能從入參去考慮傳所需要的參數,所以只能另外引入需要的變量.

適配器就是通過構造方法讓用戶傳入需要的參數對象而已.

 

三孔插頭和兩孔插座的問題.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章