設計模式之Adapter模式


說起Adapter,STL里的stack和queue都是adapter,底層是deque,隱藏了deque的一些接口,使得其可以達到FIFO是queue,LIFO是stack。

The STL stack is a container adaptor. That is, it is not a "first-class" container, but instead simply "adapts" one of the sequential first-class containers (by default, the deque) for its own purposes. So, the deque interface is restricted (i.e., much of it is hidden) so that the required LIFO (Last In, First Out) stack-like behavior is provided.

再說通透一點,adapter就是適配器,電源適配器知道吧,把220v交流電轉換為筆記本可接受的電壓和電流就是我們常見的電源適配器,手機電源適配器等等。

還有STL里本來就有一類叫做adapter,有容器adapter即stack和queue,還有迭代器的adapter,有insert iterators,reverse iterators,iostream iterators,還有仿函數的functor adapters,我印象比較深的仿函數adapter就是,可以給二元操作給一個參數也能用,等等。。STL里都寫的比較清楚。這里就不贅述了。

 

正題:

Adapter適配器模式是將兩個不兼容的類組合在一起使用。適配器起到一種轉換和包裝的作用。

Adapter設計模式主要目的組合兩個不相干類,常用有兩種方法:第一種解決方案是修改各自類的接口。但是如果沒有源碼,或者不願意為了一個應用而修改各自的接口,則需要使用Adapter適配器,在兩種接口之間創建一個混合接口。

Adapter適配器設計模式中有3個重要角色:被適配者Adaptee,適配器Adapter和目標對象Target。其中兩個現存的想要組合到一起的類分別是被適配者Adaptee和目標對象Target角色,我們需要創建一個適配器Adapter將其組合在一起。

實現Adapter適配器設計模式有兩種方式:組合(compositon, has-a關系)和繼承(inheritance,is-a關系)。

對象適配器模式使用組合,UML圖如下:

利用組合實現的Adapter模式:

就是Aapter里實際上包含一個被適配的對象。(組合)又繼承了target。因此如果要用到target的方法,直接調用父類的方法,如果要用到被適配者的方法, 就調用內部成員的函數。

//圓形,目標對象
class Cirecle{
    public void drawCircle(){
    System.out.println(“Draw circle”);
}
}
//方形,被適配對象
class Square{
    public void drawSquare(){
    System.out.println(“Draw square”);
}
}
//既可以畫圓形,又可以畫方形,適配器
public class HybridShape extends Circle{
    private Square square;
    public HybridShape(Square square){
    this.square = square;
}
public void drawSquare(){
    square.drawSquare();
}
} 


interface ICircle{
    public void drawCircle();
}
interface ISquare{
    public void drawSquare();
}
//圓形
class Cirecle implements ICircle{
    public void drawCircle(){
    System.out.println(“Draw circle”);
}
}
//方形
class Square implements ISquare{
    public void drawSquare(){
    System.out.println(“Draw square”);
}
}
//既可以畫圓形,又可以畫方形,適配器
public class HybridShape implements ICircle, ISquare{
    private ISquare square;
    private ICircle circle;
    public HybridShape(Square square){
    this.square = square;
}
public HybridShape(Circle circle){
    this.circle = circle;
}
public void drawSquare(){
    square.drawSquare();
}
public void drawCircle(){
    circle.drawCircle();
}
} 

利用多繼承方式實現Adapter模式,java里不支持多繼承,但是可以用interface實現。

先上類圖:

可以看到Adapter同時繼承了target和adaptee。

 4 //目標接口類,客戶需要的接口
 5 class Target
 6 {
 7 public:
 8     Target();
 9     virtual ~Target();
10     virtual void Request();//定義標准接口
11 };
12 
13 //需要適配的類
14 class Adaptee
15 {
16 public:
17     Adaptee();
18     ~Adaptee();
19     void SpecificRequest();
20 };
21 
22 //類模式,適配器類,通過public繼承獲得接口繼承的效果,通過private繼承獲得實現繼承的效果
23 class Adapter:public Target,private Adaptee
24 {
25 public:
26     Adapter();
27     ~Adapter();
28     virtual void Request();//實現Target定義的Request接口
29 };



 6 Target::Target()
 7 {}
 8 
 9 Target::~Target()
10 {}
11 
12 void Target::Request()
13 {
14     cout << "Target::Request()" << endl;
15 }
16 
17 Adaptee::Adaptee()
18 {
19 }
20 
21 Adaptee::~Adaptee()
22 {
23 }
24 
25 void Adaptee::SpecificRequest()
26 {
27     cout << "Adaptee::SpecificRequest()" << endl;
28 }
29 
30 //類模式的Adapter
31 Adapter::Adapter()
32 {
33 }
34 
35 Adapter::~Adapter()
36 {
37 }
38 
39 void Adapter::Request()
40 {
41     cout << "Adapter::Request()" << endl;
42     this->SpecificRequest();
43     cout << "----------------------------" <<endl;
44 }

 

在Adapter模式的兩種模式中,有一個很重要的概念就是接口繼承實現繼承的區別和聯系。接口繼承和實現繼承是面向對象領域的兩個重要的概念,接口繼承指的是通過繼承,子類獲得了父類的接口,而實現繼承指的是通過繼承子類獲得了父類的實現(並不統共接口)。在C++中的public繼承既是接口繼承又是實現繼承,因為子類在繼承了父類后既可以對外提供父類中的接口操作,又可以獲得父類的接口實現。當然我們可以通過一定的方式和技術模擬單獨的接口繼承和實現繼承,例如我們可以通過private繼承獲得實現繼承的效果(private繼承后,父類中的接口都變為private,當然只能是實現繼承了。),通過純抽象基類模擬接口繼承的效果,但是在C++中pure virtual function也可以提供默認實現(effective C++中好像有?),因此這是不純正的接口繼承,但是在Java中我們可以interface來獲得真正的接口繼承了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM