门面模式又称为外观模式,在实际开发中应用非常广泛,门面模式实现了子模块与客户端之间的松耦合关系,从而屏蔽了子模块内部的实现细节,只是将客户端需要的接口提供给客户,使得子模块的组件如果发生变化不会影响客户端的使用。这正是程序设计过程中松耦合、高内聚的体现。
简言之,门面模式就是将一些需要被外部调用的代码抽取出来,形成一个统一的接口供外部调用。以薪资计算为示例,来演示为什么要使用门面模式:
工资计算的示意代码如下:
package com.facade; public class Salary { public double getSalary(String empno) { return 2000; } }
假期天数的示意代码如下:
package com.facade; public class Holiday { public double getHoliday(String empno) { return 2; } }
计算所得税的示意代码如下:
package com.facade; public class Tax { public double getTax(String empno) { return 0; } }
客户端的示意代码如下:
package com.facade; public class Client { public static void main (String[] args) { Salary salary = new Salary(); Holiday holiday = new Holiday(); Tax tax = new Tax(); double money = salary.getSalary("100265") * holiday.getHoliday("100265") / 30 - tax.getTax("100265"); System.out.println("100265本月的工资为: " + money); } }
运行客户端,输出结果如下:
100265本月的工资为: 133.33333333333334
在上面的代码中,各个数据的获取都是在客户端进行的,如果薪资计算规则发生变化,则客户端也需要更改,需要进行松耦合:
定义接口:
package com.facade; public interface Computer { public double doSalary(String empno); }
实现代码如下:
package com.facade; public class SalaryComputer implements Computer { public double doSalary(String empno) { Salary salary = new Salary(); Holiday holiday = new Holiday(); Tax tax = new Tax(); double money = salary.getSalary(empno) * holiday.getHoliday(empno) / 30 - tax.getTax(empno); return money; } }
修改客户端代码:
package com.facade; public class Client { public static void main (String[] args) { Computer salaryComputer = new SalaryComputer(); System.out.println("100265本月的工资为: " + salaryComputer.doSalary("100265")); } }
客户端的运行结果与之前一样,此时虽然面向接口编程,但客户端还是与具体的实现类进行了关联,还可以再进行更改,采用配置文件的方式进行,在包路径下建立class.properties,示意代码如下:
class=com.facade.SalaryComputer
获取配置文件的代码如下:
package com.facade; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertiesUtil { public static Object getInstance() { Object obj = null; try { Properties p = new Properties(); InputStream in = null; try { in = Client.class.getResourceAsStream("class.properties"); p.load(in); } catch (IOException e) { e.printStackTrace(); } obj = (Computer) Class.forName(p.getProperty("class")).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return obj; } }
此时客户端的代码如下:
package com.facade; public class Client { public static void main (String[] args) { Computer computer = (Computer) PropertiesUtil.getInstance(); System.out.println("100265本月的工资为: " + computer.doSalary("100265")); } }
门面模式就是为子系统对外提供的一组接口提供一个统一的界面,使得其他系统对该系统的访问都通过这个统一的界面来完成。
当一个复杂的系统需要对外提供接口时,就需要将对外提供的接口统一封装在一个外观类里,供外系统使用。