一句话总结
装饰模式是动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。
需求
为虚拟人物设计皮肤功能,类似QQ秀。
Code V1.0
很容易的创建一个Person类,提供一些穿着能力。但是如果想增加皮肤,得修改Person类。这样就不符合开放-封闭原则了。
static func showDecorator() {
print("装扮1")
let ming = Person(name: "小明")
ming.wearTShirt()
ming.wearBigTrouser()
ming.wearSneaker()
ming.show()
print("")
print("装扮2")
ming.wearSuit()
ming.wearTie()
ming.wearLeatherShoes()
ming.show()
}
class Person {
let name: String
init(name: String) {
self.name = name
}
func wearTShirt() {
print("大T恤")
}
func wearBigTrouser() {
print("大垮裤")
}
func wearSneaker() {
print("破球鞋")
}
func wearSuit() {
print("西装")
}
func wearTie() {
print("领带")
}
func wearLeatherShoes() {
print("皮鞋")
}
func show() {
print("装扮的\(name)")
}
}
Code V2.0
可以抽出来一个装扮Finery协议,让各种皮肤类都遵守这个协议。这样增加新的皮肤的时候,只需要新增一个遵守Finery协议的皮肤类就行。但是这样还有一个问题,就是在调用皮肤类的时候,相当于把装扮过程暴露给使用方。是不合适的。
static func showDecorator() {
let ming = Person(name: "小明")
print("第一种装扮")
let _ = TShirt().show()
let _ = BigTrouser().show()
let _ = Sneaker().show()
ming.show()
print("")
print("第二种装扮")
let _ = Suit().show()
let _ = Tie().show()
let _ = LeatherShoes().show()
ming.show()
}
class Person {
var name: String = ""
init() { }
init(name: String) {
self.name = name
}
func show() {
print("装扮的\(name)")
}
}
protocol Finery {
func show()
}
class TShirt: Finery {
func show() {
print("大T恤")
}
}
class BigTrouser: Finery {
func show() {
print("大垮裤")
}
}
class Sneaker: Finery {
func show() {
print("破球鞋")
}
}
class Suit: Finery {
func show() {
print("西装")
}
}
class Tie: Finery {
func show() {
print("领带")
}
}
class LeatherShoes: Finery {
func show() {
print("皮鞋")
}
}
装饰模式
先来看一下标准的装饰模式。每个装饰对象和如何使用这个对象分离开了,每个装饰对象(例:ConcreteDecoratorA)只关心自己的功能,不需要关心如何被添加到对象链中。
static func showDecorator() {
let c = ConcreteComponent()
let d1 = ConcreteDecoratorA(component: c)
let d2 = ConcreteDecoratorB(component: d1)
d2.operation()
}
protocol Component {
func operation()
}
class ConcreteComponent: Component {
func operation() {
print("具体对象的操作")
}
}
class Decorator: Component {
let component: Component
init(component: Component) {
self.component = component
}
func operation() {
component.operation()
}
}
class ConcreteDecoratorA: Decorator {
//A特有的装饰属性
var addedState: String = ""
override func operation() {
super.operation()
addedState = "new state"
print("具体装饰对象A的操作")
}
}
class ConcreteDecoratorB: Decorator {
override func operation() {
super.operation()
addedBehavior()
print("具体装饰对象B的操作")
}
//B特有的装饰方法
func addedBehavior() { }
}
Code V3.0
使用装饰模式来实现这个需求是比较合适的。有效的把类的核心职责和装饰功能区分开了,还可以去除相关类中重复的装饰逻辑。但要注意某些场景要求调用的前后顺序。
static func showDecorator() {
let ming = Person(name: "小明")
print("第一种装扮")
let wearTShirt = TShirt(component: ming)
let wearBigTrouser = BigTrouser(component: wearTShirt)
let wearSneaker = Sneaker(component: wearBigTrouser)
wearSneaker.show()
print("")
print("第二种装扮")
let wearSuit = Suit(component: ming)
let wearTie = Tie(component: wearSuit)
let wearLeatherShoes = LeatherShoes(component: wearTie)
wearLeatherShoes.show()
}
class Person {
var name: String = ""
init() { }
init(name: String) {
self.name = name
}
func show() {
print("装扮的\(name)")
}
}
class Finery: Person {
var component: Person?
convenience init(component: Person) {
self.init()
self.component = component
}
override func show() {
component?.show()
}
}
class TShirt: Finery {
override func show() {
print("大T恤")
super.show()
}
}
class BigTrouser: Finery {
override func show() {
print("大垮裤")
super.show()
}
}
class Sneaker: Finery {
override func show() {
print("破球鞋")
super.show()
}
}
class Suit: Finery {
override func show() {
print("西装")
super.show()
}
}
class Tie: Finery {
override func show() {
print("领带")
super.show()
}
}
class LeatherShoes: Finery {
override func show() {
print("皮鞋")
super.show()
}
}