小孩睡觉模拟(Observer设计模式)

来源:互联网 发布:mac os rm rf 恢复 编辑:程序博客网 时间:2024/05/17 01:31

一小孩睡觉,醒了要东西吃,父亲就得喂他东西。

典型的模拟题。代码如下:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;class Child{private boolean wakenUp;public Child() {try {System.out.println("Child sleep.");//用新的线程模拟小孩睡觉,防止在构造函数阻塞了ExecutorService executor=Executors.newSingleThreadExecutor();executor.execute(new Runnable(){public void run(){try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}wakeup();}});} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void wakeup() {System.out.println("Child wake up.");wakenUp = true;}public boolean isWakenUp() {return wakenUp;}}class Dad implements Runnable{private Child child = null;public Dad(Child child) {this.child = child;}public void run() {while(!this.child.isWakenUp()) {try {System.out.println("Dad wait.");Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}feed();}public void feed() {System.out.println("feed child.");}}public class Main {public static void main(String[] args){Child child = new Child();new Thread(new Dad(child)).start();}}

这种题目不幼稚,就算开发多年的人都该时不时的思考一下。能做山珍海味的固然是好厨师,但能把家常的萝卜白菜给炖出了美妙的味道,那才是高手。

输出为:

Child sleep.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Dad wait.
Child wake up.
feed child.

但是,每隔一秒让父亲监测显然是不够人性化的,那么就需要将主动变为被动。在Child类中加入对Dad类的引用,从而使得在孩子醒时,主动调用Dad类的feed方法。

代码如下:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;class Child{private Dad dad=new Dad();public Child(){System.out.println("Child sleep.");ExecutorService exeService = Executors.newSingleThreadExecutor();exeService.execute(new Runnable(){public void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}wakeup();//化主动监测为被动dad.feed();}});}public void wakeup(){System.out.println("Child wake up.");}}class Dad{public void feed() {System.out.println("Feed child.");}}public class Main{public static void main(String[] args){Child child=new Child();}}

输出为:

Child sleep.
Child wake up.
Feed child.

第三版更灵活的程序,有事件,和不同的观察者。

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;class WakeupEvent {private long time;private String location;private Child source;public WakeupEvent(long time,String location,Child source){this.time = time;this.location = location;this.source = source;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public Child getSource() {return source;}public void setSource(Child source) {this.source = source;}}class Child{private Family family=null;public Child(Family family){this.family=family;System.out.println("Child sleep.");ExecutorService exeService = Executors.newSingleThreadExecutor();exeService.execute(new Runnable(){public void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}wakeup();//化主动监测为被动Child.this.family.wakeupAction(new WakeupEvent(System.currentTimeMillis(),"bed",Child.this));}});}public void wakeup(){System.out.println("Child wake up.");}}interface Family{public void wakeupAction(WakeupEvent wakeup);}class Dad implements Family{public void wakeupAction(WakeupEvent wakeup){//根据WakeupEvent的不同情况作出不同的反应//代码略System.out.println("Feed Child.");}}class GrandFather implements Family{@Overridepublic void wakeupAction(WakeupEvent wakeup) {System.out.println("Hug child.");}}public class Main{public static void main(String[] args){Child child=new Child(new GrandFather());}}

如果有多个观察者,可以用List的方式,上面的程序只有1个观察者。

输出为:

Child sleep.
Child wake up.
Hug child.

多个观察者的代码如下:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.*;class WakeupEvent {private long time;private String location;private Child source;public WakeupEvent(long time,String location,Child source){this.time = time;this.location = location;this.source = source;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public Child getSource() {return source;}public void setSource(Child source) {this.source = source;}}class Child{private List<Family> familyList=null;public Child(List<Family> list){this.familyList=list;System.out.println("Child sleep.");ExecutorService exeService = Executors.newSingleThreadExecutor();exeService.execute(new Runnable(){public void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}wakeup();//化主动监测为被动for(int i=0;i<familyList.size();i++){familyList.get(i).wakeupAction(new WakeupEvent(System.currentTimeMillis(),"bed",Child.this));}}});}public void wakeup(){System.out.println("Child wake up.");}}interface Family{public void wakeupAction(WakeupEvent wakeup);}class Dad implements Family{public void wakeupAction(WakeupEvent wakeup){//根据WakeupEvent的不同情况作出不同的反应//代码略System.out.println("Feed Child.");}}class GrandFather implements Family{@Overridepublic void wakeupAction(WakeupEvent wakeup) {System.out.println("Hug child.");}}public class Main{public static void main(String[] args){List<Family> list=new ArrayList<Family>();list.add(new Dad());list.add(new GrandFather());Child child=new Child(list);}}

输出为:

Child sleep.
Child wake up.
Feed Child.
Hug child.

当然,在代码中添加观察者还是不够灵活,最好的方式是把观察者配置在**.properties文件中,从配置文件中读取,从而添加观察者。

那么代码修改成为如下的方式。

import java.io.IOException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.*;class WakeupEvent {private long time;private String location;private Child source;public WakeupEvent(long time,String location,Child source){this.time = time;this.location = location;this.source = source;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public Child getSource() {return source;}public void setSource(Child source) {this.source = source;}}class Child{private List<Family> familyList=null;public Child(List<Family> list){this.familyList=list;System.out.println("Child sleep.");ExecutorService exeService = Executors.newSingleThreadExecutor();exeService.execute(new Runnable(){public void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}wakeup();//化主动监测为被动for(int i=0;i<familyList.size();i++){familyList.get(i).wakeupAction(new WakeupEvent(System.currentTimeMillis(),"bed",Child.this));}}});}public void wakeup(){System.out.println("Child wake up.");}}interface Family{public void wakeupAction(WakeupEvent wakeup);}class Dad implements Family{public void wakeupAction(WakeupEvent wakeup){//根据WakeupEvent的不同情况作出不同的反应//代码略System.out.println("Feed Child.");}}class GrandFather implements Family{@Overridepublic void wakeupAction(WakeupEvent wakeup) {System.out.println("Hug child.");}}public class Main{public static void main(String[] args){List<Family> list=new ArrayList<Family>();    //从配置文件中读取观察者Properties props = new Properties();try {props.load(Main.class.getClassLoader().getResourceAsStream("Observer.properties"));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}String[] obersvers = props.getProperty("Observers").split(",");for(String s:obersvers) {try {list.add((Family)Class.forName(s).newInstance());} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}Child child=new Child(list);}}

配置文件Oberser.properties的内容为:

Observers=Dad,GrandFather

运行结果为:

Child sleep.
Child wake up.
Feed Child.
Hug child.

观察者模式还用在了java.awt.Button中,Button中有一系列的观察者ActionListener,在button被按下时调用这一系列ActionListener的actionPerformed方法。

代码如下:

import java.util.*;class Button {private List<ActionListener> list = new ArrayList<ActionListener> ();public void addActionListener(ActionListener actionListener){list.add(actionListener);}public void pressButton() {for(int i=0;i<list.size();i++) {list.get(i).actionPerformed(new ActionEvent(this));}}}interface ActionListener {public void actionPerformed(ActionEvent e);}class MyActionListener implements ActionListener {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println(e.getSource()+"按钮被按了");}}class ActionEvent {private Button source;public ActionEvent(Button btn){this.source=btn;}public Object getSource() {return this.source;}}public class Test {public static void main(String[] args) {Button btn = new Button();btn.addActionListener(new MyActionListener());//当按钮被按下时btn.pressButton();}}
原创粉丝点击