在银行办业务的时候,经常会碰到如下情况:先填写一张表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是一个外观类,它集成了读档所需要的所有方法。外观模式定义了一个高层接口,使得这些子系统更容易使用,这个模式我认为是很好理解的。