編程旅途是漫長遙遠的,在不同時刻有不同的感悟,本文會一直更新下去,
思考總結
思考問題
程式呼叫第三方庫經常會遇到的問題?

你可能根本沒有程式庫的源代碼,從而無法對其進行修改,
什么是配接器模式
配接器是一種結構型設計模式, 它能使介面不兼容的物件能相互合作,
配接器模式:將一個類的介面轉換成客戶希望的另外一個介面,使得原本由于介面不兼容而不能和一起作業的那些類可以一起作業,

含義:
- 配接器模式通過封裝物件將復雜的轉換程序隱藏于幕后,被封裝的物件甚至察覺不到配接器的存在,
- 配接器不僅可以轉換不同格式的資料,其還有助于采用不同介面的物件之間的合作,
作業方式:
- 配接器實作與其中一個現有物件兼容的介面,
- 現有物件可以使用該介面安全地呼叫配接器方法,
- 配接器方法被呼叫后將以另一個物件兼容的格式和順序將請求傳遞給該物件,有時你甚至可以創建一個雙向配接器來實作雙向轉換呼叫,
何時使用:
- 當你希望使用某個類,但是其介面與其他代碼不兼容時,可以使用配接器類,
- 配接器模式允許你創建一個中間層類,其可作為代碼與遺留類、第三方類或提供怪異介面的類之間的轉換器,
- 如果您需要復用這樣一些類,他們處于同一個繼承體系,并且他們又有了額外的一些共同的方法,但是這些共同的方法不是所有在這一繼承體系中的子類所具有的共性,將缺失功能添加到一個配接器類中是一種優雅得多的解決方案,這種方式同裝飾模式非常相似,
- 通過介面轉換,將一個類插入另一個類系中,(比如老虎和飛禽,現在多了一個飛虎,在不增加物體的需求下,增加一個配接器,在里面包容一個虎物件,實作飛的介面,)
實作方式:
- 確保至少有兩個類的介面不兼容,
- 一個無法修改(通常是第三方、遺留系統或者存在眾多已有依賴的類)的功能性服務類,
- 一個或多個將受益于使用服務類的客戶端類,
- 宣告客戶端介面,描述客戶端如何與服務互動,
- 創建遵循客戶端介面的配接器類,所有方法暫時都為空,
- 在配接器類中添加一個成員變數用于保存對于服務物件的參考, 通常情況下會通過建構式對該成員變數進行初始化, 但有時在呼叫其方法時將該變數傳遞給配接器會更方便,
- 依次實作配接器類客戶端介面的所有方法,配接器會將實際作業委派給服務物件,自身只負責介面或資料格式的轉換,
- 客戶端必須通過客戶端介面使用配接器,這樣一來,你就可以在不影響客戶端代碼的情況下修改或擴展配接器,
應用實體:
- 美國電器 110V,中國 220V,就要有一個配接器將 110V 轉化為 220V,
- 在 LINUX 上運行 WINDOWS 程式,
優點:
- 可以讓任何兩個沒有關聯的類一起運行,
- 提高了類的復用, 靈活性好,
- 單一職責原則你可以將介面或資料轉換代碼從程式主要業務邏輯中分離,
- 開閉原則,客戶端代碼通過客戶端介面與配接器進行互動,你就能在不修改現有客戶端代碼的情況下在程式中添加新型別的配接器,
缺點:
- 代碼整體復雜度增加,因為你需要新增一系列介面和類,過多地使用配接器,會讓系統非常零亂,不易整體進行把握,比如,明明看到呼叫的是 A 介面,其實內部被適配成了 B 介面的實作,一個系統如果太多出現這種情況,無異于一場災難,因此如果不是很有必要,可以不使用配接器,而是直接對系統進行重構,
注意事項:
- 配接器不是在詳細設計時添加的,而是解決正在服役的專案的問題,
與其他模式的關系:
- 橋接通常會于開發前期進行設計,使你能夠將程式的各個部分獨立開來以便開發,另一方面,配接器通常在已有程式中使用,讓相互不兼容的類能很好地合作,
- 配接器可以對已有物件的介面進行修改,裝飾能在不改變物件介面的前提下強化物件功能,此外,裝飾還支持遞回組合,配接器則無法實作,
- 配接器能為被封裝物件提供不同的介面,代理能為物件提供相同的介面,裝飾則能為物件提供加強的介面,
- 外觀為現有物件定義了一個新介面,配接器則會試圖運用已有的介面,配接器通常只封裝一個物件,外觀通常會作用于整個物件子系統上,
- 橋接、狀態和策略(在某種程度上包括配接器)模式的介面非常相似,實際上,它們都基于組合模式——即將作業委派給其他物件,各自解決了不同的問題,
C# 解決方釘與圓孔問題
Adapter.cs 配接器模式
namespace 配接器模式;
public class RoundHole
{
public double Radius { private set; get; }
public RoundHole(double radius)
{
Radius = radius;
}
public bool fit(Round r)
{
return r.getRadius() <= Radius;
}
}
public class Round
{
private double radius;
protected Round()
{
}
public Round(double radius)
{
this.radius = radius;
}
public virtual double getRadius()
{
return radius;
}
}
public class Square
{
public double Side { private set; get; }
public Square(double side)
{
Side = side;
}
public double 對角線一半長()
{
return Side / 2 * Math.Sqrt(2);
}
}
public class RoundAdapter : Round
{
private Square s; // 也可以是介面
public RoundAdapter(Square s)
{
this.s = s;
}
public void setSquare(Square s)
{
this.s = s;
}
public override double getRadius()
{
return s.對角線一半長();
}
// ... 資料轉換,重寫介面方法等
}
Program.cs
using 配接器模式;
RoundHole hole = new(5);
Round r1 = new(1);
Round r2 = new(5);
Round r3 = new(10);
Console.WriteLine(hole.fit(r1));
Console.WriteLine(hole.fit(r2));
Console.WriteLine(hole.fit(r3));
Square s1 = new(5);
RoundAdapter adapter = new(s1);
Console.WriteLine(hole.fit(adapter));
adapter.setSquare(new Square(20));
Console.WriteLine(hole.fit(adapter));
Output
True
True
False
True
False
參考資料
- 《Go語言核心編程》李文塔
- 《Go語言高級編程》柴樹彬、曹春輝
- 《大話設計模式》程杰
- 《深入設計模式》亞歷山大·什韋茨
- 菜鳥教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509155.html
標籤:其他
上一篇:那些技術實戰中的架構設計方法
下一篇:Java中的SPI原理淺談
