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

考虑如下情境:

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的依赖性,但我们不希望二者耦合性太强。观察者模式很好的做到了这一点。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值