上次总结了一下耦合的三重境界。但在方法学上还是有缺陷的,那就是,在实际编码的过程中,怎样找到属于你的那个最佳依赖,最近在重读《敏捷软件开发:原则、模式与实践》,随手翻到ISP(接口隔离原则),映入眼帘的就是一个C++的例子,这个例子最大的问题就在于,他用的是老式的C++范式(不是风格,风格比这个要浅显得多),即Interface+Inheritance的做法,在实际只应该引入签名依赖的时候引入了更强的依赖:接口依赖。
里头有一个Timer:
class Timer
{
public:
void register(int timeOut, TimerClient* timerClient) = 0;
};
class TimerClient
{
public:
virtual void timeOut() = 0;
};
这是典型的Java做法!进而,这是典型的误导C++程序员。屁大一点儿事情也弄出个接口来,这么大动静干嘛呢?而且还引入了timeOut这个名字依赖(不过后面他也提议用adapter层(已经有了一个接口来,居然还再来一个adapter层)来缓解这个依赖)。
其实现代C++利用generic callback设施(tr1::function/tr2::signal)可以最直观的解决这个问题。
class Timer
{
public:
void register(int timeOut, tr1::function<void()> callback);
private:
tr2::signal<void()> callbacks;
};
// 客户代码
class TimerDoor
{
public:
void open() { timer->register(tr1::bind(onTimer, this)); }
private:
void onTimer() { ... }
Timer* timer;
};
后面还讲了一个接口隔离的例子。ATM取款机的。正好说明了高阶特性和低阶语言的尴尬,二进制兼容导致接口隔离的重要性加剧,如果是duck-typing的话或许连接口都不一定需要,反正是字符串解耦和。在duck-typing里面,客户代码天生就是仅仅依赖它们用到的那些方法的。
难怪C#要加入delegate。
--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongbaTopLanguage
http://groups.google.com/group/pongba