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