前言
软件开发过程中,客户端经常与复杂的系统内部的子系统进行耦合,从而导致客户单程序随着子系统的变化而变化,为了将他们解耦而产生是外观模式,也称作门面模式
外观模式介绍
外观模式提供了统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。即创建一个统一的类用来保证子系统中一个或多个负责的类型,客户端直接通过外观模式来调用子系统的方法,从而减少了客户端和子系统的耦合
1)实际例子
学生选择课程并且通知功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
/// <summary>
/// 以学生选课系统为例子演示外观模式的使用
/// 学生选课模块包括功能有:
/// 验证选课的人数是否已满
/// 通知用户课程选择成功与否
/// 外观类
public class RegistrationFacade
{
private RegisterCourse _registerCourse;
private NotifyStudent _notifyStudent;
public RegistrationFacade()
{
_registerCourse = new RegisterCourse();
_notifyStudent = new NotifyStudent();
}
public bool RegisterCourse(string courseName, string studentName)
{
if (!_registerCourse.CheckAvaliable(courseName))
{
return false;
}
return _notifyStudent.Notify(studentName);
}
}
public class RegisterCourse
{
public bool CheckAvaliable(string courseName)
{
Console.WriteLine("正在验证课程{0}是否人数已满", courseName);
return true;
}
}
public class NotifyStudent
{
public bool Notify(string studentName)
{
Console.WriteLine("正在向学生{0}发送通知", studentName);
return true;
}
}
}
客户端调用不使用外观模式:
void test()
{
RegisterCourse registerCourse = new RegisterCourse();
NotifyStudent notifyStudent = new NotifyStudent();
var courseName = "C#";
var studentName = "明明";
if (!registerCourse.CheckAvaliable(courseName))
{
Console.WriteLine("选课失败");
}
if (notifyStudent.Notify(studentName))
Console.WriteLine("选课成功");
else
Console.WriteLine("选课失败");
}
使用外观模式:
static void Main(string[] args)
{
RegistrationFacade facade = new RegistrationFacade();
if (facade.RegisterCourse("C#", "明明"))
Console.WriteLine("选课成功");
else
Console.WriteLine("选课失败");
}
2)外观模式介绍
使用外观模式降低了客户单和子系统的耦合度。外观模式核心是:有外观类去保存各个子系统的引用,实现由一个统一的外观类去包装多个子系统,而客户单只需要引用这个外观类,然后有外观类来调用各个子系统。
这样的模式类型与适配器模式,但是有不同:适配器是将一个对象包装起来以改变其接口,而外观模式是将一群对象包装起来以简化其接口,意图不一样。
外观类角色:客户端调用这个角色方法,该角色知道相关的一个或多个子系统的功能和自然,从客户端发出的请求委派到相应的子系统中
3)外观模式分析
优点:外观模式屏蔽了子系统组件,从而简化了接口,减少客户端处理的对象数据并使子系统的使用更加简单
外观模式实现了客户单和子系统的耦合关键,而子系统内部的功能是紧耦合的,松耦合是子系统的变化不会影响到客户端
缺点:如果修改了子系统那么需要修改外观类或客户端的源码
4)使用场景
为一个复杂的子系统提供简单的接口
提供子系统的独立性
在层次结构中,可以定义外观模式定义系统中每一层的入口