用学校为例聊聊监听器模式的演变,看丑小鸭怎么变成天鹅的 监听器观察者设计模式
先介绍下监听器模式。它的学名叫做观察者模式,因为观察者一般都取名为listener,所以越来越多的人称它为监听器模式。它的主要作用有2个,一是扩展,比如web容器的listener,就是在web.xml中配置的那种,因为web容器(比如tomcat)无法预料到开发者在启动、销毁或者其它一些事件中全部行为,所以就预留了一些listener接口;另一种作用是解耦,比如领域驱动设计(DDD)中,常将监听器和CQRS(读写分离)结合来处理业务逻辑。以提交订单为例,提交订单不仅要保存订单信息,还要修改库存,发货,短信通知等等。把他们都合在一个流程里,就会使流程臃肿,引入监听器模式,我们就能在提交订单的时候,发布一个订单事件,由各个listener自己去监听,发短信的listener监听到下单后就发短信,发货listener监听到下单后,就做发货动作。每个listener做的事情都很单一,耦合度很低。
现在让我们来看看观察者模式是怎么演变得来的。比如有个类student,然后它有个方法叫goTo(dest),dest是目标。上课铃响了,我们想让学生去教室,直接调student.goTo(教室)就行了。然后发现只有学生去教室还不行,也得让老师去教室。所以上课的时候,也要调用teacher.goTo(教室)。接着,我们发现可以提取出People接口,因为是人,都可以去一个地方。
我们在上课类里,建了个peoples列表,存储了2个people的实例:student和teacher。在上课的时候,循环调用其中的goto方法。
List<People> peoples=new ArrayList(); static{ peoples.add(new Student()); peoples.add(new Teacher()); } 上课(){ for(People p:peoples){ p.goto(教室); } }
很快,我们会发现这种方式很麻烦。比如要做早操了,在早操类里也要有上述peoples的初始化。这里我们可以引入单例模式,把peoples抽出来,放到一个第三方对象里,实例代码如下:
class PeoplesHolder{ private static PeoplesHolder holder=new holder(); private List<People> peoples; public static PeoplesHolder getHolder(){ } PeoplesHolder(){ List<People> peoples=new ArrayList(); peoples.add(new Student()); peoples.add(new Teacher()); } public void goTo(dest){ for(People p:peoples){ p.goto(dest); } } }现在,上课的时候,只要调用PeoplesHolder.getHolder().goTo(教室)。做操的时候,只要调用PeoplesHolder.getHolder().goTo(操场)就可以了。使用比之前简单许多了,代码也就优美许多了。
interface People{ 观察(条件) }以上的观察、条件是中国人的说法,外国人更喜欢用listen。也就是看和听的区别,所以观察者模式也被称为监听器模式。而条件编程语言里经常称为事件,也就是event。
interface People{ listen(event) }
interface PeopleListener{ listen(Event event) } class WalkListener implements PeopleListener{ private People; } class EatListener implements PeopleListener{ private People; } Class Event{ } class EventPublisher{ private static EventPublisher holder=new EventPublisher(); private List<PeopleListener> listeners; public static EventPublisher getHolder(){ } PeoplesHolder(){ List<PeopleListener> listeners=new ArrayList<PeopleListener>(); .... } public void publish(event){ for(People p:peoples){ p.listen(event); } } }
上一篇: 观察者模式(一)
下一篇: 关于自动化测试的一点感悟