意圖
把一個類的接口變換成客戶端所期待的另一種接口從而使原本接口不匹配而無法在一起工作的兩個類能夠在一起工作
場景
假設網絡游戲的客戶端程序分兩部分一部分是和服務端通訊的大廳部分大廳部分提供的功能有道具購買讀取房間列表創建房間以及啟動游戲程 序另一部分就是游戲程序了游戲程序和大廳程序雖然屬於一個客戶端但是由不同的公司在進行開發游戲大廳通過實現約定的接口和游戲程序進行通訊
一開始的設計就是大廳程序是基於接口方式調用游戲程序啟動游戲場景方法的在大廳程序開發接近完成的時候公司決定和另外一家游戲公司合作 因此希望把大廳程序能適用另一個游戲而這個新游戲的遵循的是另一套接口是不是可以避免修改原先調用方法來啟動場景呢?或許你會說既然只有一個方法修 改那麼修改一下也無妨我們假設大廳程序和游戲程序之間有個接口其中的大部分都有修改呢?因為游戲程序接口的修改大廳程序可能要修改不止 個地方這樣接口的意義何在呢?
此時可以考慮使用Adapter模式來適配這種接口的不匹配情況
using System;
using System
Collections
Generic;
using System
Text;
namespace AdapterExample
{
class Program
{
static void Main(string[] args)
{
Lobby lobby = new Lobby();
lobby
CreateRoom(
HalfPaper
);
lobby
StartGame();
}
}
interface IGame
{
void StartScene(string sceneName);
void EnterPlayer(string playerName);
}
class Lobby
{
private string sceneName;
public void CreateRoom(string sceneName)
{
this
sceneName = sceneName;
}
public void StartGame()
{
IGame game = new GameAdapter();
game
StartScene(sceneName);
game
EnterPlayer(
yzhu
);
}
}
class Game
{
public void LoadScene(string sceneName
string token)
{
if (token ==
Abcd
)
Console
WriteLine(
Loading
+ sceneName +
);
else
Console
WriteLine(
Invalid token!
);
}
public void EnterPlayer(int playerID)
{
Console
WriteLine(
player:
+ playerID +
entered
);
}
}
class GameAdapter : IGame
{
private Game game = new Game();
public void StartScene(string sceneName)
{
game
LoadScene(sceneName
Abcd
);
}
public void EnterPlayer(string playerName)
{
game
EnterPlayer(GetPlayerIDByPlayerName(playerName));
}
private int GetPlayerIDByPlayerName(string playerName)
{
return
;
}
}
}
可以看到原先的接口中啟動游戲場景只需要一個參數就是游戲場景名而進入新的玩家需要提供玩家ID(新游戲都使用玩家ID而不使用玩家賬戶名)
IGame接口就是適配器模式中的目標角色這是客戶所期待的接口也是針對老的游戲程序所遵循的接口
Lobby類相當於調用方或者客戶它原先的代碼可能是如下的
Game game = new Game();
但是由於接口的改變現在不能直接實例化游戲類只能實例化適配器類型雖然還是需要改動但是這個改動是很小的而且完全可以通過用動態加載程序集來消除這種改動
GameAdapter類是適配器角色它是適配器模式的核心用於把源接口轉變為目標接口在這裡我們看到它實現目標接口
Game類型是源角色或者說是需要適配的對象或許它也遵循了另外一套接口不過我們不是很關心這個因此代碼中也沒有體現
使用了適配器模式後客戶端代碼沒有做什麼修改客戶端代碼老老實實的依賴接口它並沒有錯如果因此依賴對象的修改而需要大幅度修改就很無辜 了我們在適配器中把本來沒有關聯的兩個接口適配在了一起我們可以看到適配器做的不僅僅是換一換方法名如果源角色和目標角色的差異非常大那麼適配 器需要做很多工作
何時采用
從代碼角度來說 如果你希望分離復雜類型構建規則和類型內部組成或者希望把相同的構建過程用於構建不同類型的時候可以考慮使用建造者模式
從應用角度來說 如果你希望解耦產品的創建過程和產品的具體配件或者你希望為所有產品的創建復用一套穩定並且復雜的邏輯的時候可以考慮使用建造者模式
實現要點
適配器模式是否能成功運用的關鍵在於代碼本身是否是基於接口編程的如果不是的話那麼適配器無能為力
適配器模式的實現很簡單基本的思想就是適配器一定是遵循目標接口的
適配器模式的變化比較多可以通過繼承和組合方式進行適配適配器可以是一組適配器產品適配器也可以是抽象類型
適配器模式和Facade的區別是前者是遵循接口的後者可以是不遵循接口的比較靈活
適配器模式和Proxy的區別是前者是為對象提供不同的接口或者為對象提供相同接口並且前者有一點後補的味道後者是在設計時就會運用的
注意事項
在對兩個無關類進行適配的時候考慮一下適配的代價一個非常龐大的適配器可能會對系統性能有影響
From:http://tw.wingwit.com/Article/program/net/201311/15546.html