您的位置:首页 > 其它

设计模式入门之外观者模式Facade

2014-03-29 22:58 218 查看
外观者模式在生活中的示例很多,比如组装电脑。

组装电脑有两种方式:

第一种方式是用户自己去各个零件商买零件,最终把这些零件拼在一起组成电脑;

第二种方式是找一家专门组装电脑的公司,告诉他们你的具体需求,让他们去帮你完成组装电脑的工作。

可见,第一种方式对用户的要求是很高的,需要用户了解各个组件并且需要考虑这些零件的兼容性;而第二种方式中,用户只需要告诉组装公司自己需要干什么,让组装公司去帮助自己完成就好了。第二种方式更加常见一些,原因是这种方式很简单,而且可行。

这这个例子中组装电脑的公司就相当于今天要讨论的外观者

外观者模式的作用可以总结成一句话:为外部系统提供一个界面

外观者模式:为系统外部提供一个界面。外观者让外部系统在不需要了解内部逻辑和组成的情况下实现功能。实现了外部系统与内部系统的封装隔离,松散了系统间的耦合。

案例:代码生成

public class ModelConfig {
private boolean needGenPresentation = true;
private boolean needGenBusiness = true;
private boolean needGenDAO = true;

public boolean isNeedGenPresentation() {
return needGenPresentation;
}

public void setNeedGenPresentation(boolean needGenPresentation) {
this.needGenPresentation = needGenPresentation;
}

public boolean isNeedGenBusiness() {
return needGenBusiness;
}

public void setNeedGenBusiness(boolean needGenBusiness) {
this.needNeedGenBusiness = needGenBusiness;
}

public boolean isNeedGenDAO() {
return needGenDAO;
}

public void setNeedGenDAO() {
this.needGenDAO = needGenDAO;
}
}

public class ConfigManager {
private static ConfigManager manager = null;
private static ConfigModel cm = null;

private ConfigManager() {

}

public static ConfigManager getInstance() {
if(manager == null) {
manager = new ConfigManager();
cm = new ConfigModel();
}
return manager;
}

public ConfigModel getConfigData() {
return cm;
}
}

public class Presentation {
public void generate() {
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenPresentation()) {
System.out.println("正在生成表现成代码");
}
}
}

public class Business {
public void generate() {
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenBusiness()) {
System.out.println("正在生成业务层代码");
}
}
}

public class DAO {
public void generate() {
ConfigModel cm = ConfigManager.getInstance().getConfigData();
if(cm.isNeedGenDAO()) {
System.out.println("正在生成数据层代码");
}
}
}

public class Client {
public static void main(String[] args) {
new Presentation().generate();
new Business().generate();
new DAO().generate();
}
}

从客户端的代码看出,客户端需要直接调用各个模块,这样的缺点是,并没有隐藏各个模块的具体实现,而且一旦各个模块有所改变,那客户端的逻辑可能也要收到影响,接下来引入外观者模式。
public class Facade {
public void function generate() {
new Presentation().generate();
new Business().generate();
new DAO().generate();
}
}

public class Client {
public static void main(String[] args) {
new Facade().generate();
}
}这样的话,客户端就只需要直接调用Facade进行操作就可以了,而不需要担心各个模块内部的具体实现。
但是,如果客户端除了要调用组合方法外,有时需要直接调用某个模块该怎么办呢,以下还有更好的方式:

public interface AModuleApi {
public void a1();//给外部系统调用
public void a2();//给内部调用
public void a3();//给内部调用
}

public interface BModuleApi {
public void b1();//给外部系统调用
public void b2();//给内部调用
public void b3();//给内部调用
}

public interface CModuleApi {
public void c1();//给外部系统调用
public void c2();//给内部调用
public void c3();//给内部调用
}

public interface FacadeApi {
public void a1();//这是各个模块提供给客户端调用的接口
public void b1();//这是各个模块提供给客户端调用的接口
public void c1();//这是各个模块提供给客户端调用的接口

public void test();//这是对外提供的组合接口
}

public class Client {
public static void main(String[] args) {
FacadeApi facade = new FacadeImpl();
facade.a1();
facade.b1();
facade.c1();
facade.test();
}
}

这样使得系统更加灵活,不光可以让客户端简单的调用组合方法,同时可以满足客户端对内部模块的特殊调用需求。各个模块给出接口,也隐藏了各个模块的具体实现。
外观模式优缺点:

优点:松散耦合,简单易用,更好地划分访问的层次

缺点:容易让人疑惑,到底是调用Facade好呢还是直接调用模块好呢,就好比一个人组装好电脑后,想要扩充内存,到底是找中间公司呢还是自己去买个内存条加上呢。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息