1.外观(Facade)模式的定义
- 为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
2.外观模式是“迪米特法则”的典型应用,主要优缺点
优点:
-
松散耦合,外观模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。
-
单易用,外观模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟门面类交互就可以了。
-
更好的划分访问层次-通过合理使用 Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。
缺点:
- 不能很好地限制客户使用子系统类。
- 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
3. 外观模式的主要角色
- 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
- 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
- 客户(Client)角色:通过一个外观角色访问各个子系统的功能。
4.外观模式的结构图
5.外观模式的实现,以展览车类型为例
- 创建展览车种类(奔驰,宝马,奥迪)
package com.lw.designpattern.facade; /** * @Classname BcCar * @Description 奔驰车 * @Author lw * @Date 2019-12-28 09:00 */ public class BcCar { public void showCar(){ System.out.println("奔驰E300L展览。。。。。。"); } }
package com.lw.designpattern.facade; /** * @Classname BmwCar * @Description 宝马车 * @Author lw * @Date 2019-12-28 09:00 */ public class BmwCar { public void showCar(){ System.out.println("宝马530Li展览。。。。。。"); } }
package com.lw.designpattern.facade; /** * @Classname AudiCar * @Description 奥迪车 * @Author lw * @Date 2019-12-28 09:00 */ public class AudiCar { public void showCar(){ System.out.println("奥迪A6L展览。。。。。。"); } }
- 创建展览车门面接口
package com.lw.designpattern.facade; /** * @Classname ShowCarFacade * @Description 展览车门面接口 * @Author lw * @Date 2019-12-28 09:14 */ public interface ShowCarFacade { /** * 展示汽车类型A类 */ public void showCarTypeA(); /** * 展示汽车类型B类 */ public void showCarTypeB(); /** * 展示汽车类型C类 */ public void showCarTypeC(); }
- 创建展览车门面接口实现类
package com.lw.designpattern.facade; /** * @Classname ShowCarFacade * @Description 展览车门面接口实现类 * @Author lw * @Date 2019-12-28 08:59 */ public class ShowCarFacadeImpl implements ShowCarFacade { private BcCar bcCar; private BmwCar bmwCar; private AudiCar audiCar; public ShowCarFacadeImpl(){ bcCar = new BcCar(); bmwCar = new BmwCar(); audiCar = new AudiCar(); } /** * 展示奔驰车 */ @Override public void showCarTypeA() { bcCar.showCar(); } /** * 展示奔驰车和宝马车 */ @Override public void showCarTypeB() { bcCar.showCar(); bmwCar.showCar(); } /** * 展示奔驰车、宝马车和奥迪车 */ @Override public void showCarTypeC() { bcCar.showCar(); bmwCar.showCar(); audiCar.showCar(); } }
- 单元测试
/** * 外观模式 */ @Test public void testFacade(){ // 创建门面对象 ShowCarFacade showCarFacade = new ShowCarFacadeImpl(); // 展示汽车A类 showCarFacade.showCarTypeA(); System.out.println("============"); // 展示汽车B类 showCarFacade.showCarTypeB(); System.out.println("============"); // 展示汽车C类 showCarFacade.showCarTypeC(); }
打印结果
6.外观模式的应用场景
- 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。
- 当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。
- 当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。