Author:
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:
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:
- Abstract
Window
to a superclassRectangular
as an inheritance. - 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++
E.g: Our 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()
}
...
}
}
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