引入
大家有没有比较过自己泡茶喝去茶馆喝茶的区别呢?自己泡茶需要自行准备茶叶、茶具和开水,而去茶馆喝茶,最简单的方式就是跟茶馆服务员说想要一杯什么样的茶(铁观音、碧螺春等等)。正因为茶馆有服务员,顾客无须直接和茶叶、茶具、开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可,非常简单省事。外观类就充当了软件系统中的“服务员”角色,它为多个业务类的调用提供了统一的入口,简化了类与类之间的交互。
一.名称
二.问题(为了解决什么问题)
- 为一个复杂的模块或子系统提供一个供外界访问的接口
- 子系统相对独立——外界对子系统的访问只要黑箱操作即可
- 预防低水平人员带来的风险扩散
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
三.解决方案(主要体现在uml和核心代码上)
门面模式是一个很好的封装方法,一个子系统比较复杂时,比如算法或者业务比较复杂,就可以封装出一个门面出来,项目的结构简单,而且扩展性非常好。
特点:封装性比较好
在简单的说,门面对象是外界访问子系统内部的唯一通道,不管子系统内部是怎么杂乱无章,只要门面对象在,就可以做到“金玉其外,败絮其内”。
外观模式的主要目的是降低系统的复杂程度,在面对对象的设计中,类和类的关系越多,并不能表示系统设计得越好,反而表示系统中类之间的耦合非常大,这样的系统在维护和修改时都缺乏灵活性,因为一个类的改动会导致多个类发生变化。而外观模式很大程度上降低了类之间的通信和关系。
通用代码:
门面模式使用的时候的注意事项:
- 一个子系统可以有多个门面
- 门面不参与子系统内的业务逻辑
- 外观类可以是一个单例类
- 试图通过外观类为子系统增加新行为是不对的。外观类只是提供一个集中化和简化的沟通渠道,而不是向子系统加入新行为。新行为的增加应该通过修改原有子系统类或增加新的子系统类来实现,不能通过外观类来实现。
四.例子
我们考察一个保安系统的例子,以说明门面模式的功效。一个保安系统由两个录像机、三个电灯、一个遥感器和一个警报器组成。保安系统的操作人员需要经常将这些仪器启动和关闭。
using System;
public class Camera
{
public void TurnOn()
{
Console.WriteLine("Turning on the camera.");
}
public void TurnOff()
{
Console.WriteLine("Turning off the camera.");
}
public void Rotate(int degrees)
{
Console.WriteLine("Rotating the camera by {0} degrees.", degrees);
}
}
public class Light
{
public void TurnOff()
{
Console.WriteLine("Turning on the light.");
}
public void TurnOn()
{
Console.WriteLine("Turning off the light.");
}
public void ChangeBulb()
{
Console.WriteLine("changing the light-bulb.");
}
}
public class Sensor
{
public void Activate()
{
Console.WriteLine("Activating the sensor.");
}
public void Deactivate()
{
Console.WriteLine("Deactivating the sensor.");
}
public void Trigger()
{
Console.WriteLine("The sensor has triggered.");
}
}
public class Alarm
{
public void Activate()
{
Console.WriteLine("Activating the alarm.");
}
public void Deactivate()
{
Console.WriteLine("Deactivating the alarm.");
}
public void Ring()
{
Console.WriteLine("Ringing the alarm.");
}
public void StopRing()
{
Console.WriteLine("Stop the alarm.");
}
}
public class SecurityFacade
{
private static Camera camera1, camera2;
private static Light light1, light2, light3;
private static Sensor sensor;
private static Alarm alarm;
static SecurityFacade()
{
camera1 = new Camera();
camera2 = new Camera();
light1 = new Light();
light2 = new Light();
light3 = new Light();
sensor = new Sensor();
alarm = new Alarm();
}
public void Activate()
{
camera1.TurnOn();
camera2.TurnOn();
light1.TurnOn();
light2.TurnOn();
light3.TurnOn();
sensor.Activate();
alarm.Activate();
}
public void Deactivate()
{
camera1.TurnOff();
camera2.TurnOff();
light1.TurnOff();
light2.TurnOff();
light3.TurnOff();
sensor.Deactivate();
alarm.Deactivate();
}
}
public class Client
{
private static SecurityFacade security;
public static void Main( string[] args )
{
security = new SecurityFacade();
security.Activate();
Console.WriteLine("\n--------------------\n");
security.Deactivate();
}
}
四.效果(有啥优缺点)
常见案例
文件加密模块。该模块可以对文件中的数据进行加密并将加密后的数据存储在一个新的文件中,具体的流程包括:读取源文件、加密、保存加密之后的文件。这三个操作是相互独立的,为了实现代码的独立复用,这3个操作的业务代码封装在3个不同的类中。
智能手机的一键备份功能。将原本存储在手机中的通讯录、短信、歌曲等一次性地复制到sd卡上。