场景分析
- 介绍一种场景,红烧鱼
- 假定红烧鱼包括:腌鱼,放入姜蒜、辣椒,煎鱼四个步骤,对应的类实体包括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
网友评论