假如說現在需要設計一個打印機,要適配不同的打印模式(API),然後還要按照不同的控件佈局輸出你想要的排版,解決這個問題我們只用瞭解Adapter和Bridge的設計,在我之前的博客裏已經討論過控件和實體數據(也是適配器提供的結果)的分離,今天看了《Java編程思想》關於Complete decoupling的章節,其中使用Adapter和Interface來實現完全解耦可以解決打印機對不同API的適配。
由於這種模式也是根據需求,人們慢慢總結出來的,所以我們先從最簡單的需求說起:
- 1
實現父類與子類的信息傳遞,必然會用到向上轉型。假如我們要讓一個接口根據獲取的參數不同而又不同的行爲,可以寫一個父類,然後讓子類重寫父類的方法(須是public的),那麼在類外的方法會根據不同的子類向上轉型,使用子類的特定方法(友情提示:要使用父類的方法需要加關鍵字super)。
package interfaces.classprocessor;
import java.util.*;
class Processor{
public String name(){
return getClass().getSimpleName();
}
//子類中重寫次此方法時用其他類型如string int 等
Object process(Object input){
return input;
}
}
class Upcase extends Processor{
String process(Object input){
return ((String)input).toUpperCase();
}
}
class Downcase extends Processor{
String process(Object input){
return ((String)input).toLowerCase();
}
}
class Splitter extends Processor{
String process(Object input){
return Arrays.toString(((String)input).split(" "));
}
}
public class Apply{
public static void process(Processor p,Object s){
System.out.println("Using Processor"+p.name());
System.out.println(p.process(s));
}
public static String s="this is a Sup--Sub Coupling";
public static void main(String[] args){
process(new Upcase(),s);
process(new Downcase(),s);
process(new Splitter(),s);
}
}
Apply.process()方法可以接收Processor的子類(向上轉型),並且在方法裏調用子類重寫的父類方法process(),以不同方式輸出字符串s。這種模式叫”策略設計模式”。其實就是利用多態的特性,但是Apply.process()和Processor類的耦合性太強了,如果此時遇到新的需求,封裝成類Filter,而這個類只有少部分(比如一個函數參數)與Processor類不同,那麼就要再寫一個Filter類來作爲父類,而且此時Apply.process()方法也不能使用Filter類,可見Apply.process()的複用性不強。
- 2
既然Processor有許多實現,那麼可以將其寫成接口,Filter類可以implements Processor接口,根據需求重寫其process()方法,而該重寫的方法依然保留抽象屬性(這裏的重寫就是保證方法簽名與Processor接口相同,改變其返回值,比如返回String類型。當然也可以都不改變。),再讓其子類來根據需求實現方法的具體功能,這樣Apply.process()的複用性就加強了。
- 3
上面說的Filter是繼承已有接口Processor,如果我們想用的並不是創建(created)出來的接口,而是來自外部類庫,不能修改,還是有辦法實現Filter接口與Apply.process()方法的解耦合。文章開頭提到的Adapter模式可以使用了,如果有多種於Processor類似的接口需要適配Apply.process()方法,就將它們統一到已有接口Processor:
package interfaces.interfaceprocessor;
import interfaces.filter.*;
class FilterAdapter implements Processor{
Filter filter;
public FilterAdapter(Filter filter){
this.filter=filter;
}
public String name(){return filter.name();}
public Waveform process(Object input){
return filter.process((Waveform)input);
}
}
Filter和Waveform分別是import自interfaces.filter包的接口和類,不能被修改,而適配該lib的適配器封裝了filter實例,根據filter需求(注意返回值類型已經被重寫爲Waveform)實現了Processor的方法,所以可以被Apply.process()使用,實現了接口和方法的完全解耦!