步步为营 .NET 设计模式学习笔记 十六、Facade(外观模式)
概述
在软件开发系统中,客户程序经常会与复杂系统的内部子系统之间产生耦合,而导致客户程序随着子系统的变化而变化。那么如何简化客户程序与子系统之间的交互接口?如何将复杂系统的内部子系统与客户程序之间的依赖解耦?这就是要说的Façade 模式。重新进行类的设计,将原来分散在源码中的类/结构及方法重新组合,形成新的、统一的接口,供上层应用使用。 Facade所面对的往往是多个类或其它程序单元,通过重新组合各类及程序单元,对外提供统一的接口/界面。
意图为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。[GOF 《设计模式》]
示意图
门面模式没有一个一般化的类图描述,下面是一个示意性的对象图:
图1 Façade模式示意性对象图
在这个对象图中,出现了两个角色:
门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
生活中的例子
外观模式为子系统中的接口定义了一个统一的更高层次的界面,以便于使用。当消费者按照目录采购时,则体现了一个外观模式。消费者拨打一个号码与客服代表联系,客服代表则扮演了这个"外观",他包含了与订货部、收银部和送货部的接口。
图2使用电话订货例子的外观模式对象图
示例用例图
在公司上班,每个月公司在月初都会给员工结算上一个月的薪水,首先检查输入的工号是不是公司内在职员工,检查员工的出勤率,都没有问题,再结算员工薪水,用例图如下:
代码设计
运行结先创建Employee.cs:
1 public class Employee2 {
3 public bool IsCompanyEmployee(string userID)
4 {
5 return true;
6 }
7 }
再创建Attendance.cs:
1 public class Attendance2 {
3 public bool CheckAttendance(string userID)
4 {
5 return true;
6 }
7
8 }
再创建Salary.cs:
1 public class Salary2 {
3 public decimal PayEmployeeSalary(string userID)
4 {
5 return 10000;
6 }
7 }
再创建SalarySystem.cs:
01 public class SalarySystem02 {
03 public SalarySystem()
04 {
05
06 }
07
08 public decimal GetEmplayeeSalary(string userID)
09 {
10 decimal employeeSalary = 0;
11 Employee employee = new Employee();
12 Attendance attendance = new Attendance();
13 Salary salary = new Salary();
14
15 if (!employee.IsCompanyEmployee(userID))
16 {
17 return employeeSalary;
18 }
19 if (!attendance.CheckAttendance(userID))
20 {
21 return employeeSalary;
22 }
23 employeeSalary = salary.PayEmployeeSalary(userID);
24 return employeeSalary;
25 }
26 }
最后再调用:
01 public partial class Run : Form02 {
03 public Run()
04 {
05 InitializeComponent();
06 }
07
08 private void btnRun_Click(object sender, EventArgs e)
09 {
10 //-------------------------------------
11
12 SalarySystem salarySystem = new SalarySystem();
13 string userID = "021901";
14 rtbResult.AppendText(string.Format("{1}号员工的薪水是{0}.",salarySystem.GetEmplayeeSalary(userID),userID));
15 }
16 }
果如下图:
效果及实现要点
1.Façade模式对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
2.Façade模式实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。
3.如果应用需要,它并不限制它们使用子系统类。因此你可以在系统易用性与通用性之间选择。
4.通过一个高层接口让子系统和客户端不发生直接关联,使客户端不受子系统变化的影响。
5.Facade不仅仅针对代码级别,在构架上,特别是WEB应用程序的构架上,Facade的应用非常普遍。
适用性
1.为一个复杂子系统提供一个简单接口。
2.提高子系统的独立性。
3.在层次化结构中,可以使用Facade模式定义系统中每一层的入口。
4.从代码角度来说, 如果你的程序有多个类是和一组其它接口发生关联的话可以考虑在其中加一个门面类型。
5.从应用角度来说, 如果子系统的接口是非常细的,调用方也有大量的逻辑来和这些接口发
补充:Web开发 , ASP.Net ,