设计模式-外观模式
定义:外观模式又叫门面模式,为子系统中的一组接口提供一个统一的访问接口,外观模式定义了一个高层接口,让子系统更容易使用。
下面看一个系统中多个类对象之间的调用关系
客户A需要耦合调用各个子系统,客户A需要了解所有子系统,并且与之耦合在一起,不利于扩展维护,且增加了客户的理解成本
下面看引入外观模式后类图如下
引入一个外观类,客户A只需要访问外观类,外观类来处理子系统之间的关系。当子系统需要扩展、修改时客户A不需要任何修改,一切由外观类来管理。
外观模式类图如下
Faced 外观/门面 角色
客户端调用的角色,此角色知晓子系统的所有功能和责任,本角色会将客户端发来的请求委派到相应的子系统。
Subsystem Classes 子系统角色
可以同时有一个或者多个子系统,每个子系统都不是一个单独的类,而是类的集合体,子系统并不知道外观/门面角色的存在。
看实例
公主饿了,公主要吃饭,怎么办???一般有以下几个步骤
公主去买菜、公主去买调料、没燃气了公主去充值燃气、公主去买锅,公主炒菜。
公主亲力亲为,公主太累了,公主不想什么都自己去做,公主要招聘一个保姆。
公主饿了,公主要吃饭-> 保姆买菜、保姆买调料、保姆充燃气、保姆买锅、保姆炒菜 -> 公主的饭来了
代码实现如下
// 食物抽象类、接口
public interface IFood
{
}
// 具体食物类
public class Food : IFood
{
}
Subsystem Classes 子系统角色
// 卖菜小摊
public class VegetableStand
{
// 买菜
public void Vegetable()
{
Console.WriteLine("买菜");
}
}
// 调料小摊
public class SpicesStand
{
// 买调料
public void Spices()
{
Console.WriteLine("买调料");
}
}
// 燃气站
public class GasStation
{
// 充值燃气
public void TopUp()
{
Console.WriteLine("充值燃气");
}
}
// 超市
public class Supermarket
{
// 买锅
public void BuyPot()
{
Console.WriteLine("买锅");
}
}
Faced 外观/门面 角色
// 保姆
public class Nanny
{
private VegetableStand vegetableStand;
private SpicesStand spicesStand;
private GasStation gasStation;
private Supermarket supermarket;
public IFood ReadyToCook()
{
vegetableStand = new VegetableStand();
vegetableStand.Vegetable();
spicesStand = new SpicesStand();
spicesStand.Spices();
gasStation = new GasStation();
gasStation.TopUp();
supermarket = new Supermarket();
supermarket.BuyPot();
Food food = Cooking();
return food;
}
public Food Cooking()
{
return new Food();
}
}
客户类以及调用如下
// 公主
public class Princess
{
private Nanny nanny = null;
public Princess()
{
// 招聘保姆
nanny = new Nanny();
}
// 饭来
public void RiceCome()
{
IFood food = nanny.ReadyToCook();
Console.WriteLine("公主吃饭啦");
}
}
优点
(1)减少系统的耦合
(2)提高了灵活性,子系统发生变化时,只要是不影响外观/门面角色,客户无需做任何修改
(3)提高了安全性,只能访问外观类开放出来的方法、接口。
缺点
(1)不符合开闭原则,修改麻烦