1.1概述
为系统中的一组接口提供一个一致的界面,Facade(外观)模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式是简化用户和子系统进行交互的成熟模式,外观模式的关键是为子系统提供一个称作外观的类。该外观类的实例负责和子系统中的类的实例打交道。当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。
1.2模式的结构
外观模式的结构中包括两种角色:
(1)子系统(Subsystem):子系统是若干个类的集合。这些类的实例协同合作为用户提供所需要的功能,子系统中任何类都不包含外观类的实例引用。
(2)外观(Facade):外观是一个类,该类包含子系统中全部或者部分类的实例引用,当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。
外观模式结构的类图如下所示:
1.3外观模式的优点
(1)使客户和子系统中的类无耦合,并且是子系统使用起来更加方便。
(2)外观只是提供了一个更加简洁的界面,并不影响用户直接使用子系统中的类。
(3)子系统中任何类对其方法的内容进行修改,不影响外观类的代码。
1.4适合使用外观模式的情景
(1)对于一个复杂的子系统,需要为用户提供一个简单的交互操作。
(2)不希望客户代码和子系统中的类有耦合,以便提高子系统的独立性和可移植性。
(3)当整个系统需要构建一个层次结构的子系。
1.5外观模式的具体使用
以下通过一个简单的子系统讲述外观模式中所涉及的各个角色。
报社的广告子系统有三个类CheckWord、Charge和TypeSeting类,各个类的职责如下:
CheckWord的实例负责检查广告内容含有的字符个数。
Charge类的实例负责计算费用。
TypeSeting的实例负责对广告进行排版。
使用String字符串来表示广告的内容,比如:
String content = “鲁花牌洗衣机,价格2356元,联系电话:1234567”;
现在,使用外观模式简化用户和上述子系统所进行的交互。比如,一个用户想要在报纸上刊登广告,那么用户只需要将广告的内容交给子系统的外观实例即可,外观的实例将负责和子系统中的类的实例进行交互完成用户所指派的任务。具体如下:
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:
(1)子系统(Subsystem)
子系统中的三个类CheckWord、Charge和TypeSeting,代码如下:
CheckWord.java
package com.liuzhen.seven_facade; public class CheckWord { public final int basicAmount = 85; String advertisement; int amount; public CheckWord(String advertisement){ this.advertisement = advertisement; } public void setChargeAmount(){ amount = advertisement.length() + basicAmount; //计算出计费字符数目 } public int getAmount(){ return amount; } }
Charge.java
package com.liuzhen.seven_facade; public class Charge { public final int basicCharge = 12; CheckWord checkword; Charge(CheckWord checkword){ this.checkword = checkword; } public void giveCharge(){ int charge = checkword.getAmount()*basicCharge; System.out.println("广告费用:"+charge+"元"); } }
TypeSeting.java
package com.liuzhen.seven_facade; public class TypeSeting { String advertisement; public TypeSeting(String advertisement){ this.advertisement = advertisement; } public void typeSeting(){ System.out.println("广告排版格式:"); System.out.println("*********"); System.out.println(advertisement); System.out.println("*********"); } }
(2)外观
本问题中,外观是ServerForClient类,该类的实例含有CheckWord、Charge和TypeSeting类的实例引用。ClientServerFacade类代码如下:
package com.liuzhen.seven_facade; public class ClientServerFacade { private CheckWord checkWord; private Charge charge; private TypeSeting typeSeting; String advertisment; public ClientServerFacade(String advertisment){ this.advertisment = advertisment; checkWord = new CheckWord(advertisment); charge = new Charge(checkWord); typeSeting = new TypeSeting(advertisment); } public void doAdvertisement(){ checkWord.setChargeAmount(); charge.giveCharge(); typeSeting.typeSeting(); } }
(3)具体使用
通过SevenApllication类来具体实现上述相关类和接口,来实现适配器模式的运用,其代码如下:
package com.liuzhen.seven_facade; public class SevenApplication { public static void main(String args[]){ ClientServerFacade clientFacade; String clientAdvertisement = "月光电脑,价格6356元,联系电话:2345123"; clientFacade = new ClientServerFacade(clientAdvertisement); clientFacade.doAdvertisement(); } }
运行结果:
广告费用:1320元 广告排版格式: ********* 月光电脑,价格6356元,联系电话:2345123 *********
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5