设计模式-观察者模式,在各种对象之间划分清晰的界限

来源:互联网 发布:mysql 大于小于转义 编辑:程序博客网 时间:2024/05/29 12:51

一个现实的例子

千橡的开放办公区里坐着很多女孩儿,多到超出了我对计算机、互联网企业中女孩应有数量的想象和认知。而程序员大多是单身的情商较低的脑力劳动者,他们虽然工资理想,但是除了代码和书籍,他们只能一个人过夜。而千橡的办公环境似乎在为程序员们创造机会,我甚至认为这是管理层故意而为之。这样的状况产生了一个有意思的现象,很多程序员同学都在默默地关注着一个或多个自己心仪的女孩儿,如果哪个被关注的女孩儿有什么样的举动,他们会随风而动,要么装作一起出门去吃饭要么在饮水机旁来一次”偶遇“。要是一个不曾是单身的女孩失恋了,我想那些默默关注她的程序员们会有所行动吧。这就是一个典型的观察者模式。


观察者模式

对于观察者模式的定义,网上有很多不同的定义,我在这里引用书中的一段话:

Observer- define a one-to-many dependncy between objects so that when one object changes state, all its dependents are notified and updated automatically.


普遍认同的,面向对象的编程思想是对不同概念(算法,定义,操作)的逻辑抽象与抽离,使用这一思想开发的一个主导原则是,在给定的应用程序中正确地分配任务。 系统中的每个对象应该将重点放在它所在问题域中的离散抽象上,而不是放在任何其它方面。 简而言之,一个对象只应做一件事,而且要将它做好。

而设计的意义就在于确保在对象之间划定清晰的界限,因而可提供更高的重用性和系统可维护性。观察者模式就是这样的普遍存在的设计模式。

最显而易见的案例就是表现层与逻辑层的分离,在几乎所有的(我们甚至可以讲”几乎“去掉)GUI技术中,观察者模式都发挥着作用,比如.net中的“委托/事件机制”,或swing中JButton的实现都是很好的例子。

在技术不断发展的今天,观察者模式演化出了很多与其类似的设计模式,较著名的如.net的事件模式,Qt中Signal/Slot概念等。但是他们所表达的意义却没有变,就是将各种对象之间划分出清晰的界限,同时又保持紧密的关联。


角色

尽管观察者模式有很多变体,但该模式的基本前提包含两个角色:观察者主体(熟悉 Smalltalk MVC 的人将这些术语分别称为视图和模型)。 在用户界面的环境中,观察者是负责向用户显示数据的对象。 另一方面,主体表示从问题域中模拟的业务抽象。 正如图 1 中所描述的一样, 在观察者和主体之间存在逻辑关联。 当主体对象中发生更改时,(例如,修改实例变量),观察者就会观察 这种更改,并相应地更新其显示。如同上文中提到的现实的例子一样,女孩们是主体,而程序员们则是观察者。

但是观察者模式的现实意义在于,角色的定义并非如此的简单,我们必须要明白观察者或主体并非是简单的一个种类。还以刚才的例子分析,女孩儿们,作为主体,会有不同的种类,比如有的女孩比较内敛,及时是单身也不会将这一现实显现出来。而有的女孩儿则不同,她们也许会估计将一枚戒指戴在小拇指上。而那孩儿们的分类则明了得多,比如有一些男孩儿会马上吐露心扉,有的则选择曲线救国的路线,还有的可能会比较沉得住气,过一段时间才张开攻势。无论怎样, 我们要知道,角色不是单一形式存在的。也许我们应该重新强调一下这两个角色:不同种类的观察者和不同种类的主体


角色之间的关系

我们现在知道观察者模式在逻辑上规定了观察者观察主体,但这种模式时,这实际上是一个名称误用。 更准确地说,观察者注册主体,表明它对观察的意向。 在某种状态发生变化时,主体向观察者通知这种变化情况。 当观察者不再希望观察主体时,观察者从主体中撤消注册。 这些步骤分别称为观察者注册通知撤消注册。还以上文的例子来说,我们假设每个女孩都有一个追求者名单(虽然有些不现实),当一个男孩儿喜欢一个女孩的话,   他在该名女孩的名单中注册,如果他移情别恋的时候他从这个名单中撤销。而女孩呢,只需在单身时发出广播,逐个通知名单上的每个候选者。

所以现在,我们可以确定几个必要的动作,注册,通知和撤销注册。


代码

It's time to make your hands dirty!在Java中,描述一个实体是异常简单的事情,比如一个男孩类或一个女孩类。但是考虑到给种男孩儿在面对不同女孩是表现的方法各不相同,所以要使用接口将showLove的动作抽离出来,同时为了方便女孩通知男孩儿,我们也要加入一个通知方法qualified。另一方面,对于女孩儿,要给与她们作为女性更大的权限,例如所有的对那份列表的操作以及发出通知的权利。

一个爱慕者的接口

public interface Admirer {

public void qualifiedTo(Girl thisGirl);

public void showLove();

}


一个女孩儿的类型

public abstract class Girl {

private Vector<Admirer> admirerList;

private String name;

private int age;


public Girl(String name, int age) {

setAge(age);

setName(name);

}

public  void registerAdmirer(Admirer admirer) {

this.admirerList.add(admirer);

}

public void removeAdmirer(Admirer admirer) {

this.admirerList.remove(admirer);

}

public void notifyAdmirer() {

for (Admirer admirer : admirerList)

admirer.qualifiedTo(this);

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public void setStatus(boolean isSingle, int age) {

this.setAge(age);

this.setSingle(isSingle);

if(isSingle)

notifyAdmirer();

}

}

我们可以看到,当一个女孩儿成为单身状态后,会主动的向全部的潜在爱慕者广播自己单身了的消息,而不同的爱慕者对于此消息的反应则不尽相同。

我在这里设计集中不同类型的爱慕者,他们分别是现实的男孩,情圣,害羞男孩还有专一的男孩。 他们各自对于心中爱慕的人有着不同的反应。现实的男孩关心年龄,大于心里承受年龄的人不予以接受。情圣则是来着不惧,害羞的男孩则会等上一段时间才会表白。而专一的男孩儿则只会对心中的女生采取行动。

public class RealityBoy implements Admirer {
public final int ageExcepted;

public RealityBoy(Girl girl, int ageExcepted) {
this.ageExcepted = ageExcepted;
if (girl.getAge() < ageExcepted) {
girl.registerAdmirer(this);
}
}

@Override
public void qualifiedTo(Girl thisGirl) {
if (thisGirl.getAge() > this.ageExcepted) {
return;
}
showLove();
}

@Override
public void showLove() {
System.out.println("Hi, I am the reality boy, since you are single and I love girls in your age. How about we hang out for a while?");
}
}


public class LoverBoy implements Admirer {
private Girl anyGirl;
private final List<Girl> girls;

public LoverBoy(Girl girl) {
this.anyGirl= girl;
this.girls = new ArrayList<Girl>();
girl.registerAdmirer(this);
}

@Override
public void qualifiedTo(Girl thisGirl) {
this.anyGirl = thisGirl;
showLove();
}

@Override
public void showLove() {
System.out .println("Hello there" +this.anyGirl.getName() + "  I am romantic boy , wanna to have a cup of coffee before going to a movie.");
}

public void likeThisGirl(Girl oneGirl) {
this.girls.add(oneGirl);
}

}


public class ShyBoy implements Admirer ,Runnable{
public long dormantPeriod;
private Thread t;

public ShyBoy(Girl girl, long time) {
this.dormantPeriod = time;
girl.registerAdmirer(this);
}

@Override
public void qualifiedTo(Girl thisGirl) {
t = new Thread(this);
t.start();
}

@Override
public void showLove() {
System.out
.println("Hi, I am the shy boy, I wait for "
+ dormantPeriod/ 1000
+ " seconds to get enough guts to tell you that I love you since the moment I known you were single again");
}

@Override
public void run() {
try {
t.sleep(dormantPeriod);
showLove();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


public class LoyalBoy implements Admirer {
private Girl dreamGirl;

public LoyalBoy(Girl goddress) {
setDreamGirl(goddress);
goddress.registerAdmirer(this);
}

@Override
public void qualifiedTo(Girl thisGirl) {
if (thisGirl == this.dreamGirl) {
showLove();
}
}

@Override
public void showLove() {
System.out.println("Hi, I am the persitent boy, and you are my dream girl for long time. I love you.");
}

public Girl getDreamGirl() {
return dreamGirl;
}

public void setDreamGirl(Girl dreamGirl) {
this.dreamGirl = dreamGirl;
}

}


最后,让我们一起创建一个丘比特

public class Cupid {
public static void main(String[] args) {
Girl pretty = new Girl("pretty", 24, false);
Girl amii = new Girl("amii", 21, false);
Girl vendy = new Girl("vendy", 32, false);
Girl clementina = new Girl("clementina", 25, false);


ShyBoy shy = new ShyBoy(pretty, 10000);
LoverBoy  roman = new LoverBoy(pretty);
roman.likeThisGirl(amii);
roman.likeThisGirl(vendy);
roman.likeThisGirl(clementina);
RealityBoy real = new RealityBoy(clementina, 27);
LoyalBoy loyal = new LoyalBoy(amii) ;


System.out.println("{I am Cupid, now Pretty is single}");
pretty.setStatus(true, 25);
System.out.println("{I am Cupid, now Amii is single}");
amii.setStatus(true, 22);
System.out.println("{I am Cupid, now Pretty is single}");
vendy.setStatus(true, 25);
System.out.println("{I am Cupid, now Pretty is single}");
clementina.setStatus(true, 26);
}
}



原创粉丝点击