设计模式之二--外观模式(Facade)

生活实例
    图例中的"装机公司"就是一种"外观模式",我们不需要与众多的硬打交道,只需要与装机公司联系,就可以组装电脑了       
                     


外观模式定义
    为系统中的一组接口提供一个一直的界面,Facade模式定义了一个高层接口,这个接口使得子系统更加容易使用.
  • 组件界面--从一个组件的外部来观看这个组件,能看到的界面,比如:一个类的public方法就是这个类的界面,一个模块外部看这个模块,模块的接口就是这个模块的界面.
  • 接口--模块的外部与模块之间交互的一个通道,通常是类的方法或接口方
外观模式结构图

                   
  • Facade--定义子系统的多个模块对外的高层接口,通常需要调用内部多个模块,从而把客户的请求代理给适当的子系统对象
  • 模块--接受Facade对象的委派,真正实现功能,各个模块之间可能有交互,但注意,Facade对象知道各个模块,但是各个模块不应该知道Facade对象.
                        
实例代码
/*
    A模块接口
*/
public interface AModuleApi {
    public void testA();
}
/*
    A模块实现类
*/
public class AModuleImpl implements AModuleApi {
    public void testA() {
        sysout("正在A模块,操作A方法");
    }
}
/*
    B模块接口
*/
public interface BModuleApi {
    public void testB();
}
/*
    B模块实现类
*/
public class BModuleImpl implements BModuleApi {
    public void testB() {
        sysout("正在B模块,操作B方法");
    }
}
/*
    C模块接口
*/
public interface CModuleApi {
    public void testC();
}
/*
    C模块实现类
*/
public class CModuleImpl implements CModuleApi {
    public void testC() {
        sysout("正在C模块,操作C方法");
    }
}
/*
    定义外观类
*/
public class Facade {
    public void test() {
        AModuleApi a = new AmoduleImpl();
        a.testA();
        BModuleApi b = new BmoduleImpl();
        b.testB();
        CModuleApi a = new CmoduleImpl();
        c.testC();
    }
}
/*
    客户端代码
*/
public class client {
    public static void main(String[] args) {
        new Facade().test();
    }
}
认识外观模式
  • 外观模式的目的
            外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内部多个模块的交互,松散耦合,从而让外部能够更简单的使用子系统,这点需要特别注意,因为外观模式是当作子系统对外的接口出现的,虽然可以在这里定义一些子系统没有的功能,但不建议这么做.外观应该是包装已有的功能,主要是负责组合已有功能实现客户需要,而不是添加新的实现.
  • 有何变化
            从表面上来看,只是将客户端的代码放到了Facade里面,但实际上还是有区别的,Facade相当于屏蔽了外部客户端和系统内部的模块交互,从而把A,B,C模块组合成为一个整体对外,不但方便了客户端的调用,而且封装了系统内部细节,这样如果有调用模块的算法发生变化,只需要修改Facade的界面即可,另外一个好处是,多个客户端调用的话,Facade实现了功能服用,同样的代码已经在Facade里面写好了,还有一个潜在的好处就是使用Facade的人员大大节省了学习成本,只需要了解Facade即可,无需深入学习子系统内部,去了解每个模块的细节,也不用同多个模块交互,学习也更容易.
  • 可以选择性的使用外观
            虽然有了外观,但是外部仍然是可以绕开Facade界面,而直接调用某个具体模块的接口,这样既能兼顾组合功能与细节功能,例如,客户端需要使用A模块功能,可以直接调用A模块的接口,不需调用Facade界面.

外观模式调用示意图

                   

外观模式的实现
  • 单例模式
            对于一个子系统而言,外观类不需要很多,通常可以设计为单例  
            public class Facade {
                private Facade(){
        
                }
                public static void test() {
                    AModuleApi a = new AmoduleImpl();
a.testA();
                    BModuleApi b = new BmoduleImpl();
                    b.testB();
CModuleApi a = new CmoduleImpl();
c.testC();
                }
            }
外观模式的本质

        封装交互,简单调用

何时选用外观模式
  • 如果希望为一个复杂的子系统提供一个简单接口的时候,可以考虑使用外观模式,使用外观对象来实现大部分客户端需要的功能,从而简化客户端的使用.
  • 如果想要让客户端程序和抽象的实现部分松散耦合,可以考虑使用外观模式,使用外观对象将这个子系统与它的客户分离开,从而提高子系统的独立性和可移植性.
  • 如果构建多层的系统,可以考虑使用外观模式,使用外观对象作为每层的入口,这样可以简化层见调用,也可以松散层次之间的依赖关系.
示例代码

public interface AMoudleInterface {
public void testA();
}
------------------------------------------------------------------
public class AMoudleImpl implements AMoudleInterface {
@Override
public void testA() {
System.err.println("正在操作A接口的A方法");
}
}
------------------------------------------------------------------
public interface BMoudleInterface {
public void testB();
}
------------------------------------------------------------------
public class BMoudleImpl implements BMoudleInterface {
@Override
public void testB() {
System.err.println("正在操作B接口的B方法");
}
}
------------------------------------------------------------------
//外观类,对多次操作进行封装
public class FacadeModule {
public void test() {
AMoudleImpl aMoudleImpl = new AMoudleImpl();
aMoudleImpl.testA();
BMoudleImpl bMoudleImpl = new BMoudleImpl();
bMoudleImpl.testB();
}
}
------------------------------------------------------------------
public class Client {
public static void main(String[] args) {
//外观模式封装了对一组接口的操作细节
//原始调用方法
AMoudleImpl aMoudleImpl = new AMoudleImpl();
aMoudleImpl.testA();
BMoudleImpl bMoudleImpl = new BMoudleImpl();
bMoudleImpl.testB();
System.err.println("====================================");
//外观模式后
//可以使用外观模式组合调用,也可以根据需要单独调用
FacadeModule facadeModule = new FacadeModule();
facadeModule.test();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值