在銀行辦業務的時候,經常會碰到如下情況:先填寫一張表A,再填寫一張表B,然後根據表A和表B的內容填寫表C……各種各樣的流程繞得人頭昏眼花,最後我實在受不了了,問銀行:你們這裡有沒有一條龍服務?!我好想請個秘書!把這些亂七八糟的工作丟給他做啊!
上述的例子和面板模式有些像。例如,我們有很多子系統,為了完成某項任務,它們之間的調用十分複雜,為了降低它的複雜程度,我們引入一個外觀對象(Facade,就像上面例子中的秘書一樣),讓它來完成對子系統的統一管理,如所示。
如在一個RPG遊戲中,我們需要做一個讀檔功能,讀取任務的裝備、位置,以及通過位置確定玩家所在的地圖,並且將地圖畫出來。裝備由裝備系統進行管理,地圖由地圖系統進行管理,它們之間是相互關聯的,例如,地圖系統必須知道人物的位置資訊才能構造地圖,裝備系統要知道任務的裝備才能構造出裝備,為此,我們就構造了一個讀檔器(也就是外觀對象),它把讀檔的步驟封裝起來,最終,我們只要調用這個讀檔器就可以實現對裝備系統、地圖系統的控制了。Java代碼如下:
class CharacterInfo{ private float positionX; private float positionY; private int equipmentID; public CharacterInfo(float posX, float posY, int equipmentID){ setPositionX(posX); setPositionY(posY); setEquipmentID(equipmentID); } public void setPositionX(float positionX) { this.positionX = positionX; } public float getPositionX() { return positionX; } public void setEquipmentID(int equipmentID) { this.equipmentID = equipmentID; } public int getEquipmentID() { return equipmentID; } public void setPositionY(float positionY) { this.positionY = positionY; } public float getPositionY() { return positionY; }}class Map{ private CharacterInfo characterInfo; public Map(CharacterInfo c){ characterInfo = c; } public String getMap(){ if ( characterInfo.getPositionX()> 50 && characterInfo.getPositionX()<100 && characterInfo.getPositionY()>50 && characterInfo.getPositionY()<100 ){ return "達拉然"; } else return "未知地區"; }}class MapResource{ private Map map; public MapResource(Map m){ map = m; } public void load(){ System.out.printf("正在讀取%s的地圖資訊\n", map.getMap()); }}class Equipment { private int equipmentID; public Equipment(int id){ equipmentID = id; } public void load(){ if (equipmentID == 0){ System.out.println("正在讀取武器——匕首"); } else { System.out.println("正在讀取其他武器"); } }}class CharacterLoader{ static void load(CharacterInfo info){ Map map = new Map(info); MapResource mapResource = new MapResource(map); mapResource.load(); Equipment equipment = new Equipment(info.getEquipmentID()); equipment.load(); }}class Facade{ public static void main(String[] args) { CharacterInfo character = new CharacterInfo(75, 65, 0); CharacterLoader.load(character); }}
CharacterLoader是一個外觀類,它整合了讀檔所需要的所有方法。面板模式定義了一個高層介面,使得這些子系統更容易使用,這個模式我認為是很好理解的。