委托模式定义
以下是维基百科对委托模式的定义
In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object.
委托模式是软件工程中的一种面向对象设计模式。某个对象将自己声明要完成的任务委托给另一个对象完成。
简单委托举例
(示例代码,略有简化,下同)
A使用print方法,但是A把print方法实际执行交给B
class A {
void print() {
// print is actually done here
}
}
class B {
A a = new A();
void print() {
a.print();
}
}
父类方法重载或者写wrapper方法的时候,就会用到这样的技巧。
void print() {
super.print();
// do something
}
复杂委托举例
A使用print方法,但是A把print方法的定义交给B
不同语言有不同的语法。
有的语言支持函数地址指针作为参数传递,比如C, C++,Python, Matlab等等。
再比如Java通过Interface来完成。Objective-C虽然可以使用C的方法,但是也可以通过OC的delegate语法来完成。
第一次看会觉得有些复杂。要注意有四个方面。关系相当于,小明在出差时使用iphone,但是小明不会生产手机,也不需要了解如何生产手机,而是将生产的任务“委托”给手机厂商。
第一,interface定义。手机。
第二,实现interface的类。厂商。
第三,使用interface的类。用户。
第四,告诉使用者谁是定义者。小明的手机是iphone。
以下是具体程序示例
第一,interface定义
interface Phone {
void call(Contact c); // can make phone calls
void text(Contact c); // can send text messages
}
第二,实现interface的类
class PhoneMaker implements Phone {
void call(Contact c) {
// define how a phone can make phone calls
}
void text(Contact c) {
// define how a phone can send text messages
}
}
第三,使用interface的类
class User {
Phone myPhone;
void makeAppointment() {
myPhone.call();
myPhone.text();
}
}
第四,告诉使用者谁是定义者
// somewhere in code
user.myPhone = phoneMaker;
// if in class PhoneMaker
user.myPhone = self;
MVC中的委托模式
MVC是Model-View-Controller的缩写。MVC也是一种设计模式,在图形化界面程序设计中很常见。
Model是单纯的数据和业务逻辑。View是单纯的显示模块。
controller知道并控制view和model。它将view和model联系起来并解耦。之所以是解耦的,是因为View和Model是不能直接交流的,所有在controller接口不变的情况下,可以使用多个model或者多个view,model和view不必是一一对应的关系。
MVC举例
比如,给触屏手机编程
View有两个方法,一个是显示新闻,一个是点击屏幕更新并显示新闻
class PhoneView {
void displayNews(ArrayList latestNews) {
// display latest news on screen
}
}
Model里含有新闻的数据,并且会从网络拉取新闻
class PhoneModel {
ArrayList latestNews;
void fetchLatestNewsFromServer() {
// some network code here ...
}
}
Controller将View和Model的对象作为自己的成员变量。注意,getNews实际应该新建一个线程,避免UI卡住,这里做了简化。
class PhoneController {
PhoneView v;
PhoneModel m;
void getNews() {
m.fetchLatestNewsFromServer();
v.displayNews(m.latestNews);
}
void codeEntry() {
// this may be defined by SDK provider as entry of program, or simply main method
getNews();
}
}
view和model是完全不知道controller的。程序加载,然后会调用controller的getNews方法,先更新模型,然后将模型数据传递给view显示。
这时候如果view要增加一个方法,点击屏幕更新新闻,会出现困难。因为view是不知道controller或者model的。所以没有办法更新数据。
class PhoneView {
// ...
void onScreenTouched() {
// this may be provided by SDK as input entry point
updateNews();
}
void updateNews() {
// cannot be defined here, view doesn't know about controller or model
}
}
可以用委托模式来解决这个问题。还是按照上面的四个方面。
第一,interface定义。声明updateNews方法
第二,实现interface的类。Controller
第三,使用interface的类。View
第四,告诉使用者谁是定义者 。这里比较绕,“在定义者中,告诉使用者,定义者是自己”view.updater = self
代码如下:
第一,interface定义。Java或OC可以放在某个类中,或者单独一个文件。
interface NewsUpdater {
void updateNews();
}
第二,实现interface的类。
class PhoneController implements NewsUpdater {
// ...
void getNews() {
m.fetchLatestNewsFromServer();
v.displayNews(m.latestNews);
}
void updateNews() {
// may need to do something else here
getNews();
}
}
第三,使用interface的类
class PhoneView {
NewsUpdater updater;
void onScreenTouched() {
// this may be provided by SDK as input entry point
updater.updateNews();
}
}
class PhoneController implements NewsUpdater {
// ...
void codeEntry() {
// this may be defined by SDK provider as entry of program, or simply main method
getNews();
v.updater = self;
}
}
总结
委托模式是将方法的定义和使用分离的设计模式。
MVC中,控制流通常是由C流向V,需要从V流向C的时候,可由委托模式完成。