Skip to content
Author: Tianle Yuan

Programming techniques⚓︎

Let's see some programming techniques used for design pattern.

Delegation⚓︎

For enhancing code reuse, we followed the basic principle: Favor Composition over Inheritance. The Delegation is the technique to implement the principle of Composition.

1.1 Definition⚓︎

Two objects are involved in handling a request:

\(Receving\;object\;(subclass) \xrightarrow[]{\text{delegates operations}} Delegate\;object\;(superclass)\)

    classDiagram
        direction LR
        Delegator --* Delegatee : REQUEST behavior (Operation2)
        class Delegator{
            - target : Delegatee
            + Operation()
        }
        note for Delegator "void Operation(){\n. target.Operation2(); \n}"
        class Delegatee{
            + Operation2()
        }

1.2 Example⚓︎

Let's say there is a class Window wanna calculate its area (Area1()). There are two plans:

  1. Abstract Window to a superclass Rectangular as an inheritance.
  2. Delegate area-calculate behavior to a reusable Rectangular instance.

    classDiagram
        direction BT
        Window --|> Rectangle
        class Window{
            - win_width : int
            - win_height : int
            + Area1()
        }
        note for Window "float Area1(){\n. return this->win_width * this->win_height; \n}"
        class Rectangle{
            - rec_width : int
            - rec_height : int
            + Area2()
        }
        note for Rectangle "float Area2(){\n. return this->rec_width * this->rec_height; \n}"
Window inherits the operation Area2() from Rectangle.

    classDiagram
        direction BT
        Window --* Rectangle
        class Window{
            - rectangle : Rectangle
            + Area1()
        }
        note for Window "float Area(){\n. return rectangle.Area2(window); \n}"
        class Rectangle{
            - rec_width : int
            - rec_height : int
            + Area2(ptr)
        }
        note for Rectangle "float Area2(ptr){\n. return this->rec_width * this->rec_height + ptr.info; \n}"

Window must now forward requests to its Rectangle instance explicitly.

Instead of a Window being a Rectangle, with the help of delegation, it would change to have a Rectangle.

1.3 Advantages⚓︎

  • It makes it easy to compose behaviors at run-time;
  • It makes it easy to change the way they're composed.

1.4 Improvement⚓︎

The completed delegation UML diagram can be seen below:

classDiagram
    direction LR
    Delegator(Will) ..> Interface(ScrumMaster) : Depends on behavior of
    Delegatee1(Tianle) ..|> Interface(ScrumMaster) : Realize
    Delegatee2(Yun) ..|> Interface(ScrumMaster) : Realize
    class Delegator(Will){
        - target : Interface(ScrumMaster)
        + Operation()
    }
    note for Delegator(Will) "void Operation(){\n. target.Operation2(); \n}"
    class Delegatee1(Tianle){
        + Operation2()
    }
    class Delegatee2(Yun){
        + Operation2()
    }
    class Interface(ScrumMaster){
        <<Interface>>
        + Operation2()
    }

C++
protocol ScrumMaster {
    func standup()
}

class Tianle: ScrumMaster {
    func standup() { ... }
}

class Yun: ScrumMaster {
    func standup() { ... }
}

class Will: ScrumMaster {
    static let shared = Will()
    var hasSchedulingConflict = false
    weak var target: ScrumMaster?

    private init()

    func standup() {
        guard !hasSchedulingConflict else {
            target?.standup()
        }

        ...
    }
}
E.g: Our window can become circular at run-time simply by replacing its Rectangle instance with a Circle instance, assuming Rectangle and Circle have the same type.

1.5 Use case⚓︎

Here we list the design patterns that use

  • State [Behavioral Design Pattern]
  • Strategy [Behavioral Design Pattern]
  • Visitor [Behavioral Design Pattern]

Reference⚓︎

Comments