目录
在学习observer观察者模式时发现它符合敏捷开发中的ocp开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向observer模式迈进, 最后的代码能体现出ocp原则带来的好处, 最后分享observer模式在自己的项目中的实现.
public class observer { public static void main(string[] args) { child c = new child(); dad d = new dad(c); new thread(d).start(); new thread(c).start(); } } class child implements runnable { boolean wakenup = false;//是否醒了的标志, 供父亲线程探测 public void wakeup(){ wakenup = true;//醒后设置标志为true } @override public void run() { try { thread.sleep(3000);//睡3秒后醒来. wakeup(); } catch (interruptedexception e) { e.printstacktrace(); } } public boolean iswakenup() { return wakenup; } } class dad implements runnable{ private child c; public dad(child c){ this.c = c; } public void feed(){ system.out.println("feed child"); } @override public void run() { while(true){ if(c.iswakenup()){//每隔一秒看看孩子是否醒了 feed();//醒了就喂饭 break; } try { thread.sleep(1000); } catch (interruptedexception e) { e.printstacktrace(); } } } }
public class observer { public static void main(string[] args) { dad d = new dad(); child c = new child(d); new thread(c).start(); } } class child implements runnable { private dad d;//持有父亲对象引用 public child(dad d){ this.d = d; } public void wakeup(){ d.feed();//醒来通知父亲喂饭 } @override public void run() { try { thread.sleep(3000);//假设睡3秒后醒 wakeup(); } catch (interruptedexception e) { e.printstacktrace(); } } } class dad{ public void feed(){ system.out.println("feed child"); } }
feed(child c)
方法时把自己作为参数传递给父亲, 父亲通过小孩对象就能获得小孩醒来时的具体信息.feed()
方法, 改成一个更加通用的actiontowakeupevent
, 对起床事件作出响应的方法.public class observer { public static void main(string[] args) { dad d = new dad(); child c = new child(d); new thread(c).start(); } } class child implements runnable { private dad d; public child(dad d){ this.d = d; } public void wakeup(){//通过醒来事件让父亲作出响应 d.actiontowakeupevent(new wakeupevent(system.currenttimemillis(), this)); } @override public void run() { try { thread.sleep(3000); wakeup(); } catch (interruptedexception e) { e.printstacktrace(); } } } class dad{ public void actiontowakeupevent(wakeupevent event){ system.out.println("feed child"); } } class wakeupevent{ private long time;//醒来的事件 private child source;//发出醒来事件的源 public wakeupevent(long time, child source){ this.time = time; this.source = source; } }
public class observer { public static void main(string[] args) { child c = new child(); c.addwakeuplistener(new dad()); c.addwakeuplistener(new grandfather()); c.addwakeuplistener(new dog()); new thread(c).start(); } } class child implements runnable { private arraylist<wakeuplistener> list = new arraylist<>(); public void addwakeuplistener(wakeuplistener l){//对外提供注册监听的方法 list.add(l); } public void wakeup(){ for(wakeuplistener l : list){//通知所有监听者 l.actiontowakeupevent(new wakeupevent(system.currenttimemillis(), this)); } } @override public void run() { try { thread.sleep(3000); wakeup(); } catch (interruptedexception e) { e.printstacktrace(); } } } interface wakeuplistener{ public void actiontowakeupevent(wakeupevent event); } class dad implements wakeuplistener{ @override public void actiontowakeupevent(wakeupevent event){ system.out.println("feed child"); } } class grandfather implements wakeuplistener{ @override public void actiontowakeupevent(wakeupevent event) { system.out.println("hug child"); } } class dog implements wakeuplistener{ @override public void actiontowakeupevent(wakeupevent event) { system.out.println("wang wang..."); } } class wakeupevent{ private long time; private child source;//事件源 public wakeupevent(long time, child source){ this.time = time; this.source = source; } }
false
, 然后设置坦克的生命也为false
, 最后产生一个爆炸并向服务器发送响应的消息.public boolean hittank(tank t) {//子弹击中坦克的方法 if(this.live && t.islive() && this.good != t.isgood() && this.getrect().intersects(t.getrect())) { this.live = false;//子弹死亡 t.setlive(false);//坦克死亡 tc.getexplodes().add(new explode(x - 20, y - 20, tc));//产生一个爆炸 return true; } return false; }
/** * 坦克被击中事件监听者(由坦克实现) */ public interface tankhitlistener { public void actiontotankhitevent(tankhitevent tankhitevent); } public class tankhitevent { private missile source; public tankhitevent(missile source){ this.source = source; } //省略 get() / set() 方法... } /* 坦克类 */ public class tank implements tankhitlistener { //... @override public void actiontotankhitevent(tankhitevent tankhitevent) { this.tc.getexplodes().add(new explode(tankhitevent.getsource().getx() - 20, tankhitevent.getsource().gety() - 20, this.tc));//坦克自身产生一个爆炸 if(this.blood == 20){//坦克每次扣20滴血, 如果只剩下20滴了, 那么就标记为死亡. this.live = false; tankdeadmsg msg = new tankdeadmsg(this.id);//向其他客户端转发坦克死亡的消息 this.tc.getnc().send(msg); this.tc.getnc().sendclientdisconnectmsg();//和服务器断开连接 this.tc.gameover(); return; } this.blood -= 20;//血量减少20并通知其他客户端本坦克血量减少20. tankreducebloodmsg msg = new tankreducebloodmsg(this.id, tankhitevent.getsource());//创建消息 this.tc.getnc().send(msg);//向服务器发送消息 } //... } /* 子弹类 */ public class missile { //... public boolean hittank(tank t) {//子弹击中坦克的方法 if(this.live && t.islive() && this.good != t.isgood() && this.getrect().intersects(t.getrect())) { this.live = false;//子弹死亡 t.actiontotankhitevent(new tankhitevent(this));//告知观察的坦克被打中了 return true; } return false; } //... }
如对本文有疑问, 点击进行留言回复!!
【面试题】研究过tomcat的NioEndpoint源码吗?请阐述下Reactor多线程模型在tomcat中的实现。
荐 厉害了!阿里P8架构师用4大技术文档带你深入解读爆火的中台战略
网友评论