设计模式之Observer:小孩在睡觉,醒来后要求吃东西
来源:互联网 发布:2017年进出口贸易数据 编辑:程序博客网 时间:2024/04/28 23:48
这两天在学设计模式,那么从下面这个例子来入手吧!
请模拟下列情形:
- 小孩在睡觉
- 醒来后要求吃东西
1.设计方式一
一个Child类,一个Dad类,Dad时刻监听Child,看其是否醒过来,若醒来则喂奶。
package pack1;class Child implements Runnable{private boolean WakeUp=false;public boolean isWakeUp() {return WakeUp;}public void setWakeUp(boolean wakeUp) {WakeUp = wakeUp;}@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(5000);//假设孩子睡5秒钟就醒来} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.WakeUp=true;}}class Dad implements Runnable{Child c;Dad(Child c){this.c=c;}@Overridepublic void run() {// TODO Auto-generated method stubwhile(!c.isWakeUp()){try {Thread.sleep(1000);//父亲每1秒就检查一次孩子有没有醒} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}feed(c);}private void feed(Child c) {// TODO Auto-generated method stubSystem.out.println("feed child ...");}}public class Design1 {public static void main(String[] args) {Child c=new Child();Dad d=new Dad(c);Thread threadChild=new Thread(c);Thread threadDad=new Thread(d);threadChild.start();threadDad.start();}}
上述设计方式虽然实现了基本的功能,但是由于Dad类一直主动监测Child是否醒来,浪费资源。一种简单的改进方式为,让Child醒来后主动调用Dad的Feed()方法,具体实现如下设计方式二。
2.设计方式二
Child类醒来主动调用Dad的Feed()方法。
package pack2;class Child implements Runnable{private Dad d;public Child(Dad d) {super();this.d = d;}@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(5000);//假设孩子睡5秒钟就醒来} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}d.feed(this);//孩子Child醒来主动调用Dad的feed()方法}}class Dad {public void feed(Child c) {// TODO Auto-generated method stubSystem.out.println("feed child ...");}}public class Design2 {public static void main(String[] args) {Dad d=new Dad();Child c=new Child(d);Thread threadChild=new Thread(c);threadChild.start();}}
设计方式二较好的完成了情形的模拟,节省了资源。我们考虑更复杂的一下情况,若孩子不同时间醒来,爸爸的响应要不同怎么办?
3.设计方式三
为了实现对不同时间孩子醒来的不同响应,我们把孩子醒来封装成一个事件类WakeUpEvent。
package pack3;class WakeUpEvent{private long time;private Object obj;public WakeUpEvent(long time, Object obj) {super();this.time = time;this.obj = obj;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}}class Child implements Runnable{private Dad d;public Child(Dad d) {super();this.d = d;}@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(5000);//假设孩子睡5秒钟就醒来} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}d.ActionToWakeUp(new WakeUpEvent(System.currentTimeMillis(),this));//响应醒来事件}}class Dad {public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("feed child ...");}else{System.out.println("hug child ...");}}}public class Design3 {public static void main(String[] args) {Dad d=new Dad();Child c=new Child(d);Thread threadChild=new Thread(c);threadChild.start();}}设计方式三已经较全面的模拟了孩子醒来响应的基本情形,但此种方法的扩展性不好,例如,孩子醒来爷爷奶奶也有响应又怎么办?总不能来一个响应者就修改一次源代码吧?
4.设计方式三
使用接口,让所有响应者都实现WakeUpListener接口,并在Child类中使用响应者列表,使其可以动态添加响应者。
package pack4;import java.util.ArrayList;import java.util.List;class WakeUpEvent{private long time;private Object obj;public WakeUpEvent(long time, Object obj) {super();this.time = time;this.obj = obj;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}}interface WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent);}class Child implements Runnable{private List<WakeUpListener> wakeUpListeners=new ArrayList<WakeUpListener>(); public void addWakeUpListener(WakeUpListener l){wakeUpListeners.add(l);}@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(5000);//假设孩子睡5秒钟就醒来} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//所有的响应者都对孩子醒来做出响应for(int i=0;i<wakeUpListeners.size();i++){WakeUpListener l=wakeUpListeners.get(i);l.ActionToWakeUp(new WakeUpEvent(System.currentTimeMillis(),this));}}}class Dad implements WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("Dad feed child ...");}else{System.out.println("Dad hug child ...");}}}class GrandFather implements WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("GrandFather feed child ...");}else{System.out.println("GrandFather hug child ...");}}}public class Design4 {public static void main(String[] args) {Dad d=new Dad();GrandFather gf=new GrandFather();Child c=new Child();c.addWakeUpListener(d);//添加父亲响应者c.addWakeUpListener(gf);//添加爷爷响应者Thread threadChild=new Thread(c);threadChild.start();}}此方法实现了动态添加响应者,它虽然不用修改Child类程序,但是还是要修改main()方法程序来添加响应者。
5.设计方式五
为了实现不修改任何程序而添加响应者,我们使用反射机制,通过读配置文件的方法来动态添加响应者。
若后期还需添加其他的响应者,则只需实现WakeUpListener接口,并在配置文件中加入响应类的名称条目即可,实现了无需修改源代码而动态添加响应者。
package pack5;import java.io.File;import java.io.FileInputStream;import java.util.ArrayList;import java.util.List;import java.util.Properties;class WakeUpEvent{private long time;private Object obj;public WakeUpEvent(long time, Object obj) {super();this.time = time;this.obj = obj;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}}interface WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent);}class Child implements Runnable{private List<WakeUpListener> wakeUpListeners=new ArrayList<WakeUpListener>(); public void addWakeUpListener(WakeUpListener l){wakeUpListeners.add(l);}@Overridepublic void run() {// TODO Auto-generated method stubtry {Thread.sleep(5000);//假设孩子睡5秒钟就醒来} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//所有的响应者都对孩子醒来做出响应for(int i=0;i<wakeUpListeners.size();i++){WakeUpListener l=wakeUpListeners.get(i);l.ActionToWakeUp(new WakeUpEvent(System.currentTimeMillis(),this));}}}public class Design5 {public static void main(String[] args) throws Exception {Child c=new Child();//创建配置文件File configFile=new File("wakeUpListeners.properties");Properties prop=new Properties();FileInputStream fis=new FileInputStream(configFile);prop.load(fis);for(int i=0;i<prop.size();i++){//获取响应者类名称String wakeUpListenerName=(String)prop.get("wakeUpListener"+(i+1));//根据类名称获取class文件Class clazz=Class.forName(wakeUpListenerName);WakeUpListener wakeUpListener=(WakeUpListener)clazz.newInstance();c.addWakeUpListener(wakeUpListener);}fis.close();Thread threadChild=new Thread(c);threadChild.start();}}以下分别为响应者类Dad、GrandFather、GrandMother,它们实现了统一的接口WakeUpListener,为了使用java的反射机制,都应为public类型的类。
package pack5;public class Dad implements WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("Dad feed child ...");}else{System.out.println("Dad hug child ...");}}}
package pack5;public class GrandFather implements WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("GrandFather feed child ...");}else{System.out.println("GrandFather hug child ...");}}}
package pack5;public class GrandMother implements WakeUpListener{public void ActionToWakeUp(WakeUpEvent wakeUpEvent) {// TODO Auto-generated method stubif(wakeUpEvent.getTime()<12){//不同时间对孩子的响应也不同System.out.println("GrandMother feed child ...");}else{System.out.println("GrandMother hug child ...");}}}下面为配置文件wakeUpListeners.properties。
若后期还需添加其他的响应者,则只需实现WakeUpListener接口,并在配置文件中加入响应类的名称条目即可,实现了无需修改源代码而动态添加响应者。
0 0
- 设计模式之Observer:小孩在睡觉,醒来后要求吃东西
- 小孩睡觉模拟(Observer设计模式)
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之--Observer
- 设计模式之--Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- 设计模式之Observer
- iOS编程-------UINavigationController / 界面间通信(传值)
- 三种简单写法教你Javascript对象封装
- 如何实现旅游o2o模式的网站建设
- LaTeX中表格单元格中内容自动换行 (Wrap text)问题
- java入门:JAVA和.net不同之处
- 设计模式之Observer:小孩在睡觉,醒来后要求吃东西
- 随波逐流之IOS UIslider详解
- 20个JAVA人员非常有用的功能代码
- Linux bash脚本的调用/注释和运行方式
- APP上线流程总结
- iOS编程-------UITableView表视图 / UITableViewCell的重用机制
- [leetcode] Insert sort list
- 一个并发程序开多少线程合适?
- [Python进阶-4]类的继承/多态/多重继承/任意多参数