一小孩睡觉,醒了要东西吃,父亲就得喂他东西。
典型的模拟题。代码如下:
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 block
e.printStackTrace();
}
wakeup();
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.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 block
e.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 block
e.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 block
e.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{
@Override
public 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 block
e.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{
@Override
public 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 block
e.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{
@Override
public 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 block
e.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 block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.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 {
@Override
public 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();
}
}