设计模式:委托模式Delegation Pattern在MVC中的应用

委托模式定义

以下是维基百科对委托模式的定义

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();
    }
}

这里如果调用B类对象的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的时候,可由委托模式完成。

你可能感兴趣的:(设计模式:委托模式Delegation Pattern在MVC中的应用)