天天看點

GoF之擴充卡模式、政策模式詳解

擴充卡模式(Adapter Pattern)

将一個接口轉換成客戶希望的另一個接口,使接口不相容的那些類可以一起工作,其别名為包裝器(Wrapper)。擴充卡模式既可以作為類結構型模式,也可以作為對象結構型模式。

優點

1、可以讓任何兩個沒有關聯的類一起運作。

2、提高了類的複用。

3、增加了類的透明度。

4、靈活性和擴充性都非常好,符合“開閉原則”。

缺點:

1、過多地使用擴充卡,會讓系統變複雜。比如,明明看到調用的是A 接口,其實内部被适配成了 B 接口的實作。如果不是很有必要,可以不使用擴充卡,而是直接對系統進行重構。

2.由于 JAVA至多繼承一個類,是以至多隻能适配一個适配者類,而且目标類必須是抽象類。

使用場景:有動機地修改一個正常運作的系統的接口,這時應該考慮使用擴充卡模式。

注意事項:擴充卡不是在詳細設計時添加的,而是解決正在服役的項目的問題。

類擴充卡模式(adapter pattern)

具體實作:通過電源擴充卡,将電源輸入220V(适配者)轉換為5V輸出(目标)。

//目标角色

public interface PowerTarget{

public int output5V();

}

//适配者角色

public class PowerAdaptee{

private int output = 220;

public int output220V() {

System.out.println(“電源輸出電壓:” + output);

return output;

}

}

//擴充卡角色

public class PowerAdapterextends PowerAdapteeimplements PowerTarget{

@Override

public int output5V() {

int output =output220V();

System.out.println(“電源擴充卡開始工作,此時輸出電壓是:” + output);

output = 5;

System.out.println(“電源擴充卡工作完成,此時輸出電壓是:” + output);

return output;

}

}

電源擴充卡類實作了電源目标,繼承了适配者。

//類擴充卡模式測試

public class ClassAdapterPatternTest{

public static void main(String[] args) {

PowerTargettarget = new PowerAdapter();

target.output5V();

}

}

對象擴充卡模式(object adapter pattern)

對象擴充卡模式在運作時實作target(目标)接口。在這種擴充卡模式中,擴充卡包裝了一個類執行個體。擴充卡通過調用包裝對象執行個體的方法實作适配。

代碼示例和類擴充卡模式隻有Adapter類有不同,其他都一樣,隻貼上Adapter類。

//擴充卡角色

public class PowerAdapterimplements PowerTarget{

private PowerAdaptee powerAdaptee;

public PowerAdapter(PowerAdapteepowerAdaptee) {

super();

this.powerAdaptee = powerAdaptee;

}

@Override

public int output5V() {

int output = powerAdaptee.output220V();

System.out.println(“電源擴充卡開始工作,此時輸出電壓是:” + output);

output = 5;

System.out.println(“電源擴充卡工作完成,此時輸出電壓是:” + output);

return output;

}

}

實作了PowerTarget(目标角色),在建立對象時引入PowerAdaptee(适配者角色)。

預設擴充卡模式(defaultadapter pattern)(用戶端,繼承b,調用b中的方法,不必直接實作a(直接實作a需要實作a中的所有的方法))

當不需要全部實作接口提供的方法時,可以設計一個擴充卡抽象類實作接口,并為接口中的每個方法提供預設方法,抽象類的子類就可以有選擇的覆寫父類的某些方法實作需求,它适用于一個接口不想使用所有的方法的情況。

在java8後,接口中可以有default方法,就不需要這種預設擴充卡模式了。接口中方法都設定為default,實作為空,這樣同樣同樣可以達到預設擴充卡模式同樣的效果。

政策模式(Strategy Pattern)也叫 政策模式(Policy Pattern)。

指的是對象具備某個行為,但是在不同的場景中,該行為有不同的實作算法。比如一個人的交稅比率與他的工資有關,不同的工資水準對應不同的稅率。

優點:

1、算法可以自由切換。

2、避免使用多重條件判斷。

3、擴充性良好。

缺點:

1、政策類會增多。

2、所有政策類都需要對外暴露。

具體實作:建立加減乘算法族,解決在有多種算法相似的情況下,使用 if…else 所帶來的複雜和難以維護。

//建立一個接口,定政策或算法的行為。

public interface Strategy{

public int doOperation(int num1, int num2);

}

//建立實作接口的實體類,裡面包含具體的政策或算法實作。利用多态,使行為在不同場景下産生不同結果。

public class OperationAddimplements Strategy{

@Override

public int doOperation(int num1, int num2) {

return num1 + num2;

}

}

public class OperationSubstractimplements Strategy{

@Override

public int doOperation(int num1, int num2) {

return num1 - num2;

}

}

public class OperationMultiplyimplements Strategy{

@Override

public int doOperation(int num1, int num2) {

return num1 * num2;

}

}

//建立Context類,用來操作政策的上下文環境,屏蔽高層子產品(用戶端)對政策,算法的直接通路,封裝可能存在的變化;

public class Context {

private Strategy strategy;

public Context(){

}

public SetStrategy(Strategy strategy){

this.strategy = strategy;

}

public int executeStrategy(int num1, int num2){

return strategy.doOperation(num1, num2);

}

}

//使用 Context 來檢視當它改變政策 Strategy 時的行為變化。

public class StrategyPatternClient{

public static void main(String[] args) {

Contextcontext = new Context();

context.SetStrategy(new OperationAdd());

System.out.println(“10 + 5 =” + context.executeStrategy(10, 5));

context.SetStrategy(new OperationSubstract());

System.out.println(“10 - 5 =” + context.executeStrategy(10, 5));

context.SetStrategy(new OperationMultiply());

System.out.println(“10 * 5 =” + context.executeStrategy(10, 5));

}

}

輸出結果:

10 + 5 = 15

10 - 5 = 5

10 * 5 =50

注意事項:如果一個系統的政策多于四個,就需要考慮使用混合模式,解決政策類膨脹的問題。

https://mp.weixin.qq.com/s/g20WQyzJNmvkH-kLPZRYBA

歡迎關注微信公衆号“專注一行代碼