Design Pattern: Decorator Pattern

I. Giới thiệu:


Decorator Pattern là một Design Pattern thuộc nhóm Structural. Nó cho phép chúng ta thêm các behavior mới cho một object (wrapped object) bằng cách đặt object đó vào trong một object khác (wrapper object) chứa đựng behaviour cần được thêm vào.

  • Component Interface: định nghĩa các thuộc tính và phương thức cho wrapperwrapped object.
  • Concrete Component: là wrapped object cơ bản, nó cho phép các Decorator có thể wrap nó bên trong để thêm các behavior mới. Concrete Component sẽ được implement Component Interface.
  • Base Decorator: là class cha của các Concrete Decortor, nó cũng được implement Component Interface. Bên trong Decorator sẽ chứa object của một wrapped object và cũng sẽ có những phương thức giống với wrapped object đó.
  • Concrete Decorator: class kế thừa Base Decorator, là nơi định nghĩa các behavior mới cần được thêm vào wrapped object.

II. Cách thức hoạt động:


Decorator Pattern hoạt động theo cơ chế tạo ra nhiều object là các Concreate Decorator để bao bọc lẫn nhau. Mỗi khi cần thêm một behavior mới cho object thì Decorator Pattern sẽ tạo ra một Concreate Decorator để xử lý behaviorConcrete Decorator này sẽ là object mới (wrapper object) bao bọc object cũ (wrapped object).

III. Decorator Pattern được sử dụng khi nào?


Decorator Pattern được sử dụng khi muốn thêm behavior vào một object mà không muốn thay đổi cấu trúc của object đó.

IV. Ví dụ:


Component protocol

protocol Component {

    func operation() -> String
}

Concrete Component

class ConcreteComponent: Component {

    func operation() -> String {
        return "ConcreteComponent"
    }
}

Base Decorator

class Decorator: Component {

    private var component: Component

    init(_ component: Component) {
        self.component = component
    }

    /// The Decorator delegates all work to the wrapped component.
    func operation() -> String {
        return component.operation()
    }
}

Concrete Decorator

class ConcreteDecoratorA: Decorator {

    /// Decorators may call parent implementation of the operation, instead of
    /// calling the wrapped object directly. This approach simplifies extension
    /// of decorator classes.
    override func operation() -> String {
        return "ConcreteDecoratorA(" + super.operation() + ")"
    }
}

class ConcreteDecoratorB: Decorator {

    override func operation() -> String {
        return "ConcreteDecoratorB(" + super.operation() + ")"
    }
}

Sử dụng

class Client {

    static func someClientCode(component: Component) {
        print("Result: " + component.operation())
    }
}

print("Client: I've got a simple component")
let simple = ConcreteComponent()
Client.someClientCode(component: simple)

let decorator1 = ConcreteDecoratorA(simple)
let decorator2 = ConcreteDecoratorB(decorator1)
print("\nClient: Now I've got a decorated component")
Client.someClientCode(component: decorator2)

V. Tài liệu tham khảo: