適配器結構圖:
Target(目標接口) | 可以是接口或抽象類,由於c#不支持多類繼承,因此把Target定義爲接口 |
Adaptee(需要適配的類接口) | 不滿足當前條件,需要轉化的類 |
Adapter(適配器) | 負責Adaptee的接口與Target接口進行適配 |
優點:
- 通過適配器,客戶端可以調用同一接口,因而對客戶端來說是透明的。這樣做更簡單、更直接、更緊湊。
- 複用了現存的類,解決了現存類和複用環境要求不一致的問題。
- 將目標類和適配者類解耦,通過引入一個適配器類重用現有的適配者類,而無需修改原有代碼。
- 一個對象適配器可以把多個不同的適配者類適配到同一個目標,也就是說,同一個適配器可以把適配者類和它的子類都適配到目標接口。
缺點:
對於對象適配器來說,更換適配器的實現過程比較複雜
適配器模式適用情形:
- 當適用一個已存在的類,而它的接口不符合所要求的情況;
- 想要創建一個可以複用的類,該類可以與原接口的類協調工作;
- 在對象適配中,當要匹配數個子類的時候,對象適配器可以適配它們的父類接口。
類的適配器模式:
//Target(目標接口) 需要的電壓
public interface America_Dian
{
int Dian_110();
}
//Adaptee(需要適配的類接口) 現有的電壓
public class China_Dian
{
public int Dian_220()
{
return 220;
}
}
//Adapter(適配器) 110v電壓變爲220v電壓
public class Transform_Dian:China_Dian,America_Dian
{
public int Dian_110()
{
int tempDianV = this.Dian_220();
if(tempDianV == 220)
{
return 110;
}
Debug.Log("沒有電壓成功,這回好了,機器燒了");
return tempDianV;
}
}
public class ImportedMachine
{
public void Work(int _dianV)
{
if(_dianV == 110)
{
Debug.Log("變壓成功,美國進口機器在中國運行正常");
}
}
}
public void Start()
{
Transform_Dian tempTransform_Dian = new Transform_Dian();
//進口美國電器還是用美國的充電線 但是經過變壓器把電壓從220v升到了110v
int tempDianV = tempTransform_Dian.Dian_110();
ImportedMachine tempMachine = new ImportedMachine();
//升壓後,
tempMachine.Work(tempDianV);
}
對象適配器:
//Target(目標接口) 需要的電壓
public interface America_Dian
{
int Dian_110();
}
//Adaptee(需要適配的類接口) 現有的電壓
public class China_Dian
{
public int Dian_220()
{
return 220;
}
}
//Adapter(適配器) 110v電壓變爲220v電壓
//不用繼承而是委派
public class Transform_Dian:America_Dian
{
//直接關聯被適配類
private China_Dian m_chinaDian;
public Transform_Dian(China_Dian _chinaDian)
{
this.m_chinaDian = _chinaDian;
}
public int Dian_110()
{
int tempDianV = m_chinaDian.Dian_220();
if(tempDianV == 220)
{
return 110;
}
Debug.Log("沒有電壓成功,這回好了,機器燒了");
return tempDianV;
}
}
public class ImportedMachine
{
public void Work(int _dianV)
{
if(_dianV == 110)
{
Debug.Log("變壓成功,美國進口機器在中國運行正常");
}
}
}
public void Start()
{
Transform_Dian tempTransform_Dian = new Transform_Dian(new China_Dian());
//進口美國電器還是用美國的充電線 但是經過變壓器把電壓從110v升到了220v
int tempDianV = tempTransform_Dian.Dian_110();
ImportedMachine tempMachine = new ImportedMachine();
//升壓後,
tempMachine.Work(tempDianV);
}
對象適配器和類適配器其實算是同一種思想,只不過實現方式不同。
根據合成複用原則,組合大於繼承,
所以它解決了類適配器必須繼承Adaptee的侷限性問題,也不再強求Target必須是接口。
同樣的它使用成本更低,更靈活
接口適配器:
//不同電器,電機所需電壓不同
public interface DianYa
{
int Output5v();
int Output10v();
int Output15v();
int Output20v();
}
//適配器 抽象類實現接口,而在抽象類中所有的方法都進行置空
public abstract class Adapter:DianYa
{
public int Output5v()
{
return 220;
}
public int Output10v()
{
return 220;
}
public int Output15v()
{
return 220;
}
public int Output20v()
{
return 220;
}
}
//本類根據需要,從繼承的抽象類中,選擇性的實現自己需要的方法
public class Phone:Adapter
{
public int Output5v()
{
int tempOutputV = base.Output5v();
if(tempOutputV == 220)
{
Debug.Log("220->5 變壓成功,手機可以充電了");
return 5;
}
Debug.Log("變壓失敗,這回好了,手機燒了");
return tempOutputV;
}
}
public class Computer:Adapter
{
public int Output15v()
{
int tempOutputV = base.Output15v();
if(tempOutputV == 220)
{
Debug.Log("220->15 變壓成功,電腦可以充電了");
return 15;
}
Debug.Log("變壓失敗,這回好了,電腦燒了");
return tempOutputV;
}
}
public void Start()
{
Phone tempPhone = new Phone();
tempPhone.Output5v();
Computer tempComputer = new Computer();
tempComputer.Output15v();
}
- 類適配器,以類給到,在Adapter裏,就是將Adaptee當做類,繼承,
- 對象適配器,以對象給到,在Adapter裏,將Adaptee作爲一個對象,持有。
- 接口適配器,以接口給到,在Adapter裏,將Adaptee作爲一個接口,實現。
參考:
https://www.cnblogs.com/libingql/p/3495699.html
https://www.jianshu.com/p/9d0575311214