观察者模式(又称发布订阅模式)

故事开头
小菜对大鸟说:“今天白天真是笑死我了,我们一同事在上班期间看股票行情,被老板当场抓到,老板很生气,后果很严重”
“最近股市那么火,也是应该可以理解的,你们老板说不定也炒股。”
“其实最近项目计划安排的很紧,是比较忙的。而最近股市又特别的火,所以很多人都在偷偷的通过网页看行情,老板会时常出去办事,于是大家就可以轻松一点,看看行情,几个人聊聊买卖股票的心得什么的,但是一不小心老板就回来了,让老板看到在工作当中做这些总是不太好你猜他们想到怎么办?”
“只能小心点,那能怎么办”
“我们公司前台秘书是一个小美眉,他的名字叫童子喆,因为平时同事们买个饮料或者零食什么的,都拿一份孝敬给她,所以关系比较好,现在他们就请小子喆帮忙,如果老板回来了,就一定打个电话进来,大家也好马上各就各位,这样就不会被老板发现问题了。”
“哈,好主意,老板被人当卧底了,这下你们就不怕被发现了。”
“是呀,只要老板进门了,子喆只要博通一个人的电话给其中一个同事,所有人就知道回来了,这种办法屡试不爽”
“那怎么还会有今天被发现的事?”
“今天是这样的,老板出门后,大家开始个个都打开股票行情查看软件,然后还聚在一起讨论着‘大盘现在如何’,‘你的股票抛了没有’等事。这时老板回来后,并没有直接走进去,而是对子喆交代了几句,可能是要她打印点东西,并叫她跟老板去拿材料,这样子喆就根本没有时间去打电话了。”
“哈,这下完了。”
“是呀,老板带着子喆走进办公室的时候,办公室一下子从热闹转向了安静,好几个同事本是聚在一起聊天的,赶快不说话了,回到自己座位上,最可怜的是那个背对大门的同事——魏关姹,他显然不知道老板回来了,竟然还叫了一句‘我的股票涨停了哦’,声音很大,就当他转过身想表达一下下激动的心情的时,却看到老板愤怒的面孔和其他同事的眼神。”
“幸运却又倒霉的人,谁叫他没看到老板来呢。”
但我们老板很快恢复了笑容,平静的说道:“魏关姹,恭喜发财啊,是不是考虑请我们大家吃饭哦。”,魏关姹面红耳赤的说:“老板,实在对不起!以后不会了。”“以后工作时还是好好工作吧。大家都继续工作吧。”老板没再说什么,就忙事情去了。”
“啊,就这样就结束了?我还以为他会拿魏关姹做典型,好好批评一顿呢,不过回头想想来看,你们老板其实很厉害,这比直接批评来得更有效,大家都是明白人,给个面子或许谁都能下得了台,如果真的当面批评,或许魏关姹真就干不下去了。”
“是的,生气却不发作,很牛。”
上面这个故事就是一个典型的观察者模式又称发布订阅模式,同事是订阅者,前台是发布者,前台发布消息,订阅的同事收到消息后回到自己座位。

前台类(发布者)

class Dep{
	//存贮每一个观察者对象(每一位同事)
	ArrayList<wather> subs = new ArrayList<observer>();
	//添加一个订阅着(需要通知同事)
	public void Add(wather sub) {
		this.subs.add(sub);
	}
	//删除一个订阅者(不需要通知的同事)
	public void Dele(observer sub) {
		// TODO Auto-generated method stub
		this.subs.remove(sub);
	}
	//发送通知(通知每一个被观察的观察者去更新自己状态)
	public void Notify() {
		// TODO Auto-generated method stub
		for (observer wather : subs) {
			wather.update();
		}
	}
}

订阅者(同事)

class stockObserver{
	String name;
	public wather(String name) {
		this.name = name;
	}
	public void update() {
		System.out.println(this.name+"回到自己座位");
	}
}

客户端如下

static void main(String[] args){
	//前台小姐姐 童子喆
	Dep tongzizhe = new dep;
	stockObserver tongshi1 = new stockObserver("魏关姹");
	stockObserver tongshi2 = new stockObserver("易管查");
	//前台记录通知这两个同事
	tongzizhe.Add(tongshi1);
	tongzizhe.Add(tongshi2);
	//老板回来后(通知两位同事)
	tongzizhe.Notify();
}
	

运行结果如下

魏关姹回到自己座位
易管查回到自己座位

“写的不错,把整个事情都包括的,但是你有没有发现,这个‘前台类’和‘看股票者’类之间怎么样?”
“嗯,你是不是指的相互耦合?我写的时候就感觉到了,前台类需要增加观察者,观察者需要前台的状态。”
“对呀,你想想看,如果观察者中还有人正在看NBA的网上直播,你的‘前台’类怎么办?”
“那就得改动了。”
“你都发现了这个问题了,你说怎么办?想想我们的设计原则”
“我就知道,你又要提醒我了。首先开放-封闭原则,修改原有的代码就说明设计的不好。其次是依赖倒转原则,我们应该让程序依赖抽象,而不是依赖对象。OK我去改改”

增加抽通知者接口

interface subject {
	public void Add(observer sub);
	public void Dele(observer sub);
	public void Notify();
}

具体的通知类可能是前台,也可能是老板,像最后一次,被老板抓到后也需要自己回到座位,但是他们也许有一些各自的方法,但是对于通知者来说,它们是一样的,所以他们都去实现这个接口

class Boss implements subject{
	ArrayList<observer> subs = new ArrayList<observer>();

	@Override
	public void Add(observer sub) {
		this.subs.add(sub);
	}
	@Override
	public void Dele(observer sub) {
		// TODO Auto-generated method stub
		this.subs.remove(sub);
	}
	@Override
	public void Notify() {
		// TODO Auto-generated method stub
		for (observer wather : subs) {
			wather.update();
		}
	}
}

前台秘书与老板类似,略……
对于具体的观察者,需要改的地方就是把与‘前台’耦合的地方都改成针对抽象者通知

//抽象观察者
abstract class observer {
	private String name;
	public observer(String name) {
		this.setName(name);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public abstract void update();
}
class stockObserver extends observer{
	public wather(String name) {
		super(name);
	}
	@Override
	public void update() {
		System.out.println(this.getName()+"回到工位");
	}
}

客户端代码如下

public static void main(String[] args) {
		subject boss = new Boss();
		observer observer1 = new stockObserver ("魏关姹");
		observer observer2 = new stockObserver ("易管查");
		boss.Add(observer1);
		boss.Add(observer2);
		//没有通知魏关姹被抓没有回到自己工位上
		boss.Dele(observer1 );
		boss.Notify();
	}

运行结果

易管查回到工位
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值