简话设计模式之Observer(观察者)模式

来源:互联网 发布:mac ttf字体 编辑:程序博客网 时间:2024/06/06 12:29

考虑如下情境:

class A{functionA(){1;}}
1,我们想要拓展functionA()的功能;2,我们希望在不同的情况下functionA()有不同的实现(多态)。想到多态,我们可以想到用继承实现:

class childA extends A{functionA(){1;2;}}class childB extends A{functionA(){1;3;}}

上面的方式在平时实现各种多态功能时经常用到,面向对象编程的一个基本原则是面向接口编程,而不是面向对象,因此我们对上述方式进行抽象,并且用template method模板方法模式实现上述情境:

abstract class A{functionA(){1;functionB()}abstract functionB();}class childA extends A{functionA(){1;2;functionB();}functionB(){...}}

记得《Java编程思想》一书中提到,使用继承是因为childA和A在逻辑上有很强的关联性,也就是说childA is like A。如果二者并没有很强的关联性,而仅仅只是为了使用继承实现上述情境。那么使用继承并不是一个恰当的选择,严格的说违背了“继承”这一词的意义。我们知道,除了继承,组合也是面向对象语言中一个重要的实现多态的方法。先看如下用组合实现的上述情境:

class A{B b = new childB1();functionA(){b.functionB();}}interface B{functionB();}class childB1 implements B{
functionB(){
}

}

仔细观察上述代码,我们可以把B抽象成接口,然后对于B b = new childB1()。不同情境下我们给出不同的实现,从而很好的解决了上述问题,但这依然不是完美的解决方案,因为我们发现在new childB1()生成B的子类对象时,这个子类是写死了的,也就是说A和childB1的依赖性很强,这对于程序设计来说是一个很不好的现象,为了降低这种依赖性,我们考虑下述解决方案:

class A{B b;functionA(){attach(new childB1());b.functionB();}attach(B b){this.b = b;}}interface B{functionB();}class childB1 implements B{functionB(){}}
发现二者的区别了么,在类A中专门开辟了一个attach()方法动态的加载B对象,说到此,与平时想见的许多Android源码似乎有种似曾相识的感觉。如果换一下函数和类名称就明白了:

class A{OnClickListener listener;functionA(){setOnClickListener(new myOnClickListener());listener.onClick();}setOnClickListener(OnClickListener listener){this.listener = listener;}}interface OnClickListener{onClick();}class myOnClickListener implements OnClickListener{onClick(){}}

这就是观察者模式。这中模式的来由我们可以从上述实际情境得到,它的优势我们可以借助GOF对该模式的总结说明:“我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性”,也就是说我们保持类A在功能上对类B的依赖性,但我们不希望二者耦合性太强。观察者模式很好的做到了这一点。



0 0
原创粉丝点击