“Effective C++”中第六部分“继承与面向对象设计中”,Scott Meyers谈论了许多c++面向对象设计中的技巧,其对is-a与has-a、继承还是符合的论述都颇为精彩,值得一看。在条款35:“考虑virtual以外的其它选择”中,Scott Meyers提到两种考虑的技巧——NVI手法与Strategy模式。这里,NVI手法就是模板方法设计模式,这个模式貌似不在那经典的gof设计模式中,不过在框架的设计中可是随处可见,例如:spring的设计、Hibernate的设计、Android中的Binder的设计等等。以Android中Binder的BBinder对象为例:
class BBinder : public IBinder { public: BBinder(); virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); …… protected: virtual ~BBinder(); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); …… };如果了解过Binder机制的实现,便知当有服务请求到来时,Binder驱动便会调用transact处理请求,从BBinder的transact函数的实现可以看出,其真正的实现是在onTransact中,onTransact是protected的,所以Service的实现类只需要实现onTransact,在其中实现自己的应用逻辑即可。
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { data.setDataPosition(0); status_t err = NO_ERROR; switch (code) { case PING_TRANSACTION: reply->writeInt32(pingBinder()); break; default: err = onTransact(code, data, reply, flags); break; } if (reply != NULL) { reply->setDataPosition(0); } return err; }
这个设计模式的使用一方面使得可以在onTransact的前后可以做一些事情,上面的代码可以看出,这有点类似“装饰模式“——之前有写过其作用,看到这里的时候还特意回去比较了下两者的区别=。=,我的看法是“装饰模式”更像是两个继承体系下的情况,它是基于组合的,装饰者作为component中的一个对象,当采用不同的装饰时,便能实现不同的组合。而方法模板设计模式更像是在一个继承体系中,如果研究过spring等的源码实现会深有体会,public的函数transact只是决定了什么时候调用onTransact,而onTransact的具体技术实现则是交给其继承者实现。这可能就是其优势的地方。
“策略模式”
情景:在某个功能模块中,我们需要计算物体的体积,但不同物体的体积计算方式是不一样的,而且将来可能会有新的物体会添加到系统中,因此我们也希望能保证在不改变原来系统功能的情况下,扩展系统。