1. 何为装饰模式
1.1 定义:
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式的结构图如图1-1所示:
图1-1 装饰模式结构图1.2 装饰模式的特点:
(1)装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2)装饰对象包含一个真实对象的引用(reference)。
(3)装饰对象接受所有来自客户端的请求,它把这些请求转发给真实的对象。
(4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改改定对象的结构就可以增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
2. 情景设置
我们在买车时,有很多的车型(Suv, Mpv等等)供我们去选择,也有很多配件供我们去选择,要实现选择车型和车的配件这一过程,我们可以创建很多的类去实现。但是车型很多,车的配件更多,我们为每一种情况都去创建一个类,显然是不现实的。
对于这种情景,使用装饰模式去解决无疑是一个很不错的选择。根据以上的描述我们将此场景抽象为下面的结构图,如图2-1所示:
图2-13. 代码实现
// Component
protocol Car {
// 多少钱
func howMuch()-> Int
// 展示装配的配件
func showParts()
}
// ConcreteComponents
class Suv: Car {
init(owner: String) {
print("\(owner)买了一辆Suv,10W")
}
func howMuch() -> Int {
return 10
}
func showParts() {}
}
class Mpv: Car {
init(owner: String) {
print("\(owner)买了一辆Mpv,15W")
}
func howMuch() -> Int {
return 15
}
func showParts() {}
}
// Decorator
class CarParts: Car {
var car: Car?
func howMuch() -> Int {
return car?.howMuch() ?? 0
}
func showParts() {
car?.showParts()
}
func decorator(_ car: Car) -> Car {
self.car = car
return self
}
}
// ConcreteDecorators
class Sofa: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 1
}
override func showParts() {
super.showParts()
print("选配了真皮沙发,1W")
}
}
class Safety: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 3
}
override func showParts() {
super.showParts()
print("选配了全套安全系统,3W")
}
}
class Engine: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 5
}
override func showParts() {
super.showParts()
print("选配了V8发动机,5W")
}
}
客户端调用:
// wc1买一辆suv
var suv: Car = Suv(owner: "wc1")
// 装配沙发
suv = Sofa().decorator(suv)
// 装配发动机
suv = Engine().decorator(suv)
// 装配安全系统
suv = Safety().decorator(suv)
suv.showParts()
print("一共花了\(suv.howMuch())W")
// wcl买一辆mpv
var mpv: Car = Mpv(owner: "wcl")
// 装配发动机
mpv = Engine().decorator(mpv)
// 装配安全系统
mpv = Safety().decorator(mpv)
mpv.showParts()
print("一共花了\(mpv.howMuch())W")
控制台输出:
wc1买了一辆Suv, 10W 选配了真皮沙发,1W 选配了V8发动机,5W 选配了全套安全系统,3W 一共花了19W wcl买了一辆Mpv, 15W 选配了V8发动机,5W 选配了全套安全系统,3W 一共花了23W
4. 装饰模式的优缺点
优点:
(1)可以将类中装饰功能从类中搬出去,简化原有的类
(2)有效的将核心职责和装饰功能区分开来,而且可以除去相关类中重复的装饰逻辑
缺点:
(1)装饰模式虽然扩展性较高,类的数量较多,如何取舍可扩展性和间接性是个问题,有选择就要有所牺牲
(2)很难搞清楚一个类究竟被装饰了多少层,可能是1层,也可能是100层
网友评论