1. 外观模式简介
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简化接口,隐藏了一个复杂系统的内部子系统,并提供了一个统一的接口给客户端。
2. 用一个通俗的例子来理解外观模式
让我们以餐厅点餐服务员的例子来解释外观模式。
在一个餐厅中,顾客通过服务员来点餐,而服务员则负责与厨房、厨师等各个部门协调,为顾客提供所需的食物。在这个例子中,服务员充当了一个外观,隐藏了厨房等子系统的复杂性,提供了一个简化的接口给顾客。
下面是一个简化的 Python 代码示例,演示了餐厅点餐服务员(外观)如何与厨房子系统协调:
# 子系统:厨房
class Kitchen:
def prepare_dish(self, dish_name):
print(f"正在准备 {dish_name}")
# 外观类:服务员
class Waiter:
def __init__(self):
self.kitchen = Kitchen()
def take_order(self, dish_name):
print(f"顾客点了 {dish_name}")
self.kitchen.prepare_dish(dish_name)
print(f"{dish_name} 已准备好,上菜!")
# 客户端:顾客
def client():
waiter = Waiter()
dish_names = [
"水煮鱼",
"啫啫鸡煲",
"咸虾酱炒通菜",
"乳鸽老火汤",
"白米饭"
]
for name in dish_names:
waiter.take_order(name)
if __name__ == "__main__":
client()
在这个例子中,client 函数代表顾客点餐。Waiter 类代表服务员,它隐藏了厨房的复杂性,为顾客提供了一个简单的点餐接口。当顾客点餐时,服务员负责与厨房协调,准备所需的菜品。
这个例子中,Waiter 类就是外观,它隐藏了厨房子系统的复杂性,并提供了一个简化的接口给客户端。
3. 外观模式的结构
外观模式的UML通常如下所示(图例来自外观模式):
由图可知,外观模式往往包括以下几个实体:
-
外观 (Facade) 提供了一种访问特定子系统功能的便捷方式, 其了解如何重定向客户端请求, 知晓如何操作一切活动部件。
-
附加外观 (Additional Facade) 可以避免多种不相关的功能污染单一外观, 使其变成又一个复杂结构。 客户端和其他外观都可使用附加外观。
-
复杂子系统 (Complex Subsystem,可选) 由数十个不同对象构成。 如果要用这些对象完成有意义的工作, 你必须深入了解子系统的实现细节, 比如按照正确顺序初始化对象和为其提供正确格式的数据。子系统类不会意识到外观的存在, 它们在系统内运作并且相互之间可直接进行交互。
-
客户端 (Client) 使用外观代替对子系统对象的直接调用。
4. 简单练习:【设计模式专题之外观模式】9-电源开关
"""
【设计模式专题之外观模式】9-电源开关
时间限制:1.000S 空间限制:256MB
题目描述
小明家的电源总开关控制了家里的三个设备:空调、台灯和电视机。每个设备都有独立的开关密码,分别用数字1、2和3表示。即输入1时,空调关闭,输入2时,台灯关闭,输入3时,电视机关闭,当输入为4时,表示要关闭所有设备。请你使用外观模式编写程序来描述电源总开关的操作。
输入描述
第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。
接下来的 N 行,每行包含一个数字,表示对应设备的开关操作(1表示关闭空调,2表示关闭台灯,3表示关闭电视机,4表示关闭所有设备)。
输出描述
输出关闭所有设备后的状态,当输入的数字不在1-4范围内时,输出Invalid device code.
输入示例
4
1
2
3
4
输出示例
Air Conditioner is turned off.
Desk Lamp is turned off.
Television is turned off.
All devices are off.
"""
class AirConditioner:
def turnOff(self):
print("Air Conditioner is turned off.")
class DeskLamp:
def turnOff(self):
print("Desk Lamp is turned off.")
class TV:
def turnOff(self):
print("Television is turned off.")
class Facade:
def __init__(self):
self.ac = AirConditioner()
self.dl = DeskLamp()
self.tv = TV()
def turnOff(self, deviceCode: str):
if deviceCode == "1":
self.ac.turnOff()
elif deviceCode == "2":
self.dl.turnOff()
elif deviceCode == "3":
self.tv.turnOff()
elif deviceCode == "4":
print("All devices are off.")
else:
print("Invalid device code.")
def client():
facade = Facade()
n = int(input())
for _ in range(n):
deviceCode = input()
facade.turnOff(deviceCode)
if __name__ == "__main__":
client()