在物件導向程式設計中,有個守則叫做:
「多用合成,少用繼承」(Composition over inheritance)
而Delegation就是一個用合成取代繼承的好方法。
"Delegate"
Definition
很多華語圈的開發者可能都對"Delegate"這個字有點陌生,我們先看看劍橋字典的解釋:
delegate /ˈdel.ɪ.ɡeɪt/ (v.)
to give a particular job, duty, right, etc. to someone else so that they do it for you
(把…)委派(給…),(把…)委託(給…);授權(給…)
在軟件工程的意思就是把一個class想做的功能委託給其他class幫忙做。
Delegation pattern
使用了這種「委託」式做法的程式設計,稱為「委託模式(Delegation pattern)」,最常見於C#、Objective-C和Swift。
The delegation design pattern allows an object to delegate one or more tasks to a helper object. [ref]
Part of speech
Delegate這個字還有幾種forms,也是常用,不要搞亂:
- delegate (v.) - (把…)委派(給…)
- delegate (n.) - 被委託者
- delegator (n.) - 委託者
- delegation (n.) - (一份)委託
Delegation vs Inheritance
"Delegation"和"Inheritance"經常可以做到相同的效果,例如以下的例子:
Inheritance
例如有個叫IMonitor
的interface,有些顯示器是彩色的,有些是黑白的,於是你設計出兩種sub-classes:
public interface IMonitor {
public void display();
}
public class ColorMonitor implements IMonitor {
public void display() {
System.out.println("Something colourful");
}
}
public class BWMonitor implements IMonitor {
public void display() {
System.out.println("Something in B&W");
}
}
ColorMonitor monitor = new ColorMonitor();
monitor.display(); // Something colourful
Delegation
這次我們只用一種顯示器,然後把display()
delegate給其他class去做。
首先建立負責display()
的delegates:
public interface DisplayDelegate {
public void display();
}
public class ColorDisplayDelegate implements DisplayDelegate {
public void display() {
System.out.println("Something colourful");
}
}
public class BWDisplayDelegate implements DisplayDelegate {
public void display() {
System.out.println("Something in B&W");
}
}
然後在class裡面儲起一個負責display()
的delegate:
public interface IMonitor {
public void display();
}
public class ConcreteMonitor implements IMonitor {
private DisplayDelegate displayDelegate;
public ConcreteMonitor() {
// Set up a delegate for displaying
this.displayDelegate = new ColorDisplayDelegate();
}
public void display() {
this.displayDelegate.display();
}
}
ColorMonitor monitor = new ColorMonitor();
monitor.display(); // Something colourful
兩種做法最後效果相同。
那為甚麼要用Delegation?
Delegation最大的好處是Run-time flexibility。
假設上述例子,雖然你有一部彩色顯示器 ColorMonitor monitor
,但你可能會想把它當作黑白顯示器 BWMonitor
用,在這情況下,Class的繼承是不能在Run-time改變的。
但對於Delegation卻是輕而易舉,只需要把monitor
裡面的displayDelegate
由彩色換成黑白的,就完全無痛改造了這個顯示器啦!
References
- Delegation Pattern (Best Practice Software Engineering)
- Delegation design pattern
- When to use delegation instead of inheritance?
- Delegation vs Inheritance in Java
- When would I use the delegation pattern instead of inheritence to extend a class's behavior?
- When to Use Delegates Instead of Interfaces (C# Programming Guide)
- Delegates vs Interfaces in C#