Head First设计模式之装饰者模式

定义

Decorator Pattern

在不改变接口的情况下,动态的扩展一个对象的功能。通过包装对象来实现,又称为wrapper模式。
装饰者模式采用组合的方式,依赖于抽象,能够动态的扩展功能。

涉及到的角色有:
Component:定义了一个接口,包含所需要的功能
ConcreteComponent:具体的组件
Decorator:装饰者,持有Component的实例,与Component有一样的接口。
ConcreteDecorator:具体的装饰者。负责给对象扩展功能。

UML图

  • 装饰者和被装饰者有着相同的类型
  • 可以用多个装饰者装饰一个对象
  • 装饰者可以在被装饰者原有行为之前或之后,添加自己的行为。
  • 被装饰对象可以被装饰对象所代替。

实现例子

还是拿Head First上的例子。

一个咖啡馆里有深焙咖啡,脱因咖啡等,可以加摩卡、奶泡、牛奶等等其他的调料,需要计算出各种种类的价钱。比如深焙咖啡+摩卡,脱因咖啡+摩卡+奶泡,xx咖啡+其他调料等等。

其实这里咖啡就是被装饰者,其他的调料就是装饰者。

代码如下:github地址

protocol Component {
    func getDescription() -> String
    func cost() -> Double
}

// 具体被装饰者,深焙咖啡
class DarkRoast: Component {
    func getDescription() -> String {
        return "DarkRoast"
    }
    
    func cost() -> Double {
        return 10.0
    }
}

// 脱因咖啡
class Decaf: Component {
    func getDescription() -> String {
        return "Decaf"
    }
    
    func cost() -> Double {
        return 20.0
    }
}

// 装饰者基类
class Decorator: Component {
    var obj: Component
    
    init(obj: Component) {
        self.obj = obj
    }
    
    func getDescription() -> String {
        return obj.getDescription()
    }
    
    func cost() -> Double {
        return obj.cost()
    }
}

// 牛奶
class Milk: Decorator {
    override func getDescription() -> String {
        return self.obj.getDescription() + " Milk"
    }
    
    override func cost() -> Double {
        return 2.0 + self.obj.cost()
    }
}

// 摩卡
class Mocha: Decorator {
    override func getDescription() -> String {
        return self.obj.getDescription() + " Mocha"
    }
    
    override func cost() -> Double {
        return 3.0 + self.obj.cost()
    }
}

// 奶泡
class Whip: Decorator {
    override func getDescription() -> String {
        return self.obj.getDescription() + " Whip"
    }
    
    override func cost() -> Double {
        return 4.0 + self.obj.cost()
    }
}

调用:

// 现在我需要一杯深焙咖啡+摩卡
var darkRoast: Component = DarkRoast()
darkRoast = Mocha(obj: darkRoast)

print("深焙咖啡+摩卡,\(darkRoast.getDescription()),cost:\(darkRoast.cost())")
// output:深焙咖啡+摩卡,DarkRoast Mocha,cost:13.0

// 脱因咖啡+奶泡+牛奶,可被多个装饰者装饰。
var decaf: Component = Decaf()
decaf = Whip(obj: decaf)
decaf = Milk(obj: decaf)

print("脱因咖啡+奶泡+牛奶,\(decaf.getDescription()),cost:\(decaf.cost())")
// output:脱因咖啡+奶泡+牛奶,Decaf Whip Milk,cost:26.0

// 深焙咖啡+双倍摩卡+牛奶
var darkRoast1: Component = DarkRoast()

darkRoast1 = Mocha(obj: darkRoast1)
darkRoast1 = Mocha(obj: darkRoast1)
darkRoast1 = Milk(obj: darkRoast1)

print("深焙咖啡+双倍摩卡+牛奶,\(darkRoast1.getDescription()),cost:\(darkRoast1.cost())")
//output:深焙咖啡+双倍摩卡+牛奶,DarkRoast Mocha Mocha Milk,cost:18.0


你可能感兴趣的:(Head First设计模式之装饰者模式)