facade 门面(外观)模式

场景分析
  • 介绍一种场景,红烧鱼
  • 假定红烧鱼包括:腌鱼,放入姜蒜、辣椒,煎鱼四个步骤,对应的类实体包括Fish, Ginger, Pepper, client 执行制作红烧鱼的动作时,可以单独一个一个调用,但如果包括十几个步骤时,直接让Client接触十几个类是比较粗暴的,可以在 Client 和 功能实体类之间,添加一层封装类-Facade,facade 将以功能单位进行封装划分,定义出包含若干环节的接口,如将红烧鱼的所有环节封装到fryFish 接口中
  • 病人看病的案例,Client 即病人,需要与 挂号、门诊、取药、化验等直接打交道,乱、复杂,若出现一个 接待人员 facade 代替病人与各个系统打交道,则会减轻Client的复杂性
  • java的三层开发模式
角色定义
  • 门面角色
    • 客户端直接调用这个门面的方法,门面方法知晓子系统的功能和责任,且会将Client的请求委派到相应子系统中
  • 子系统角色
    • 可以同时有一个或多个子系统,每个子系统都可以直接被Client 调用,也可被门面调用
    • 对于子系统而言,它并不知晓门面的存在,门面于它来讲,只是另一个Client而已
代码展示
  • Fish
public class Fish {

    //把鱼腌一下
    public void pickleFish() {
        System.out.println("腌鱼");
    }

    //煎鱼
    public void fryFish() {
        System.out.println("煎鱼");
    }
}
  • Ginger
/**
 * 姜
 */
public class Ginger {

    //放入姜片
    public void fryGinger(){
        System.out.println("热油放入姜片");
    }
}

  • pepper
/**
 * 辣椒
 */
public class Pepper {
    //放入辣椒
    public void fryPepper() {
        System.out.println("炒辣椒");
    }
}
  • 定义 facade
/**
 * 定义红烧鱼的facade
 */
public class FishFacade {

    //把材料准备好:鱼,辣椒,姜片
    private Fish fish;
    private Ginger ginger;
    private Pepper pepper;

    //准备材料
    public FishFacade() {
        //定义材料
        fish = new Fish();
        ginger = new Ginger();
        pepper = new Pepper();
    }

    //红烧鱼有若干步骤的,这里将所有分散步骤统一
    //该方法即所谓的 facade,以煎鱼为整体功能模块,封装了很多繁杂的环节,避免Client 直接各自调用
    //这里我们只是定义菜料,有可能中间还要让老婆帮忙系下围裙,或者让儿子买包盐去呢
    //总之是很多繁杂的逻辑
    public void fryFish() {
        //先把鱼腌一下
        fish.pickleFish();
        //放入辣椒
        pepper.fryPepper();
        //放入姜片
        ginger.fryGinger();
        //煎鱼
        fish.fryFish();
    }

}
  • 定义 Demo
public class FacadeDemo {

    public static void main(String[] args) {
        
        FishFacade fishFacade = new FishFacade();
        
        //调用 facade
        fishFacade.fryFish();
        
        //如果不使用 facade 则 单步执行
        //腌鱼
        //fish.pickleFish();
        
        //油放姜片
        //ginger.fryGinger();
        
        //油放辣椒
        //pepper.fryPepper();
        
        //煎鱼
        //fish.fryFish();
    }

}
优缺点
  • 优点
    • 对 Client 屏蔽了子系统的复杂性,降低了Client 与 子系统的直接交互
    • 实现子系统与 Client 的松耦合,使得子系统的变化不会影响到Client,只需更改 facade 类即可
    • 降低了大型软件系统的编译依赖性,简化了系统在不同平台之间的移植过程 ???
    • 只是提供了一个访问子系统的统一入口并不影响用户直接使用子系统
  • 缺点
    • 不能很好的限制Client对子系统的使用(Client可以直接调用子系统)
    • 不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类客户端代码,违背开闭原则
其他注意点
  • 一个系统可以有多个外观类
    • 通常只需要一个外观类,且此外观类只有一个实例,即单例类,可以节省资源
    • 系统可以设计多个外观类,每个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能
  • 不要试图通过外观类为子系统增加新的行为
    • 不要通过继承一个外观类在子系统中加入新行为,外观的用意是为子系统提供一个集中化和简化的沟通渠道,而非向子系统加入新行为,新行为的增加应该通过修改原有子系统或增加新的子系统实现
  • 外观模式与迪米特法则
    • 外观类充当了 Client 和 子系统之间的第三者,降低了Client 和 子系统的耦合
  • 抽象外观类的引入
    • 外观类缺点违背了开闭原则,当增加新的系统或者移出子系统时需要修改外观类,可以通过引入抽象外观类解决一定的问题,对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类关联新的子系统对象

参考:http://blog.csdn.net/xingjiarong/article/details/50066133

你可能感兴趣的:(facade 门面(外观)模式)