观察者模式
观察者--OOD线程
简单理解
起一个被观察者线程和一个观察者线程。观察者不断的循环检查被观察者状态是否发生改变。此设计缺点,因为需要不断的循环进行监视,所以耗CPU资源。
举例场景
孩子在睡觉,醒后要吃东西,父亲不断的监视者看孩子有没有醒
代码实现
child
package observersOOD;
/**
* 观察者模式-OOD线程
* 起一个被观察者线程和一个观察者线程。观察者不断的循环检查被观察者状态是否发生改变
* 案例:孩子在睡觉,醒后要吃东西,父亲不断的监视者看孩子有没有醒
*/
public class Child implements Runnable{
private boolean wakenUp = false;
public boolean isWakenUp() {
return wakenUp;
}
public void setWakenUp(boolean wakenUp) {
this.wakenUp = wakenUp;
}
public void wakeUp(){
System.out.println("孩子醒了....");
wakenUp = true;
}
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
wakeUp();
}
}
Dad类
package observersOOD;
public class Dad implements Runnable {
private Child child;
public Dad(Child child) {
this.child = child;
}
public void feed(Child child){
System.out.println("feed child......");
}
public void run() {
while (!child.isWakenUp()){
try {
System.out.println("我在监视孩子。。。。");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
feed(this.child);
}
public static void main(String[] args) {
Child child = new Child();
Dad dad = new Dad(child);
Thread childThread = new Thread(child);
Thread dadThread = new Thread(dad);
childThread.start();
dadThread.start();
}
}
test
public static void main(String[] args) {
Child child = new Child();
Dad dad = new Dad(child);
Thread childThread = new Thread(child);
Thread dadThread = new Thread(dad);
childThread.start();
dadThread.start();
}
运行结果
我在监视孩子。。。。
我在监视孩子。。。。
我在监视孩子。。。。
我在监视孩子。。。。
孩子醒了....
feed child......
改进(上面由于父类需要主动监视孩子,需要通过不断的循环实现,太浪费资源)。
改进后有孩子醒后主动通知父亲。
class Child implements Runnable {
private Dad dad;
public Child(Dad dad) {
this.dad = dad;
}
public void wakeUp(){
dad.feed(this);
}
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
wakeUp();
}
}
class Dad {
void feed(Child c) {
System.out.println("feed child");
}
}
public class Test {
public static void main(String[] args) {
Dad d = new Dad();
Child c = new Child(d);
new Thread(c).start();
}
}
把孩子睡醒后封装成事件
class WakenUpEvent{
private long time;
private String location;
private Child source;
public WakenUpEvent(long time, String location, Child source) {
super();
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 implements Runnable {
private Dad dad;
public Child(Dad dad) {
this.dad = dad;
}
public void wakeUp(){
dad.actionToWakenUp(new WakenUpEvent(System.currentTimeMillis(), "bed", this));
}
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
wakeUp();
}
}
class Dad {
public void actionToWakenUp(WakenUpEvent e) {
System.out.println(e.getTime());
System.out.println(e.getLocation());
System.out.println(e.getSource());
System.out.println("Fedd the child");
}
}
public class Test {
public static void main(String[] args) {
Dad d = new Dad();
Child c = new Child(d);
new Thread(c).start();
}
}
上面例子中child都会持有dad类,如果观察者发生改变,需要修改代码很不方便。
解决方法:动态的注册到被观察者中。持有addListener方法
定义监听者接口
interface WakenUpListener {
public void actionToWakenUp(WakenUpEvent e);
}
定义实际监听者
class Dad implements WakenUpListener {
public void actionToWakenUp(WakenUpEvent e) {
System.out.println("Fedd the child");
}
}
class GrandFather implements WakenUpListener {
public void actionToWakenUp(WakenUpEvent e) {
System.out.println("抱孩子");
}
}
定义child,child中持有添加观察者方法,当醒后一一通知他的观察者
package observersOOD.Listener;
import java.util.ArrayList;
import java.util.List;
public class Child implements Runnable{
public Child() {
}
private List<WakenUpListener> wakenUpListeners = new ArrayList<WakenUpListener>();
//提供一个注册观察者方法
public void addWakenUpListener(WakenUpListener wakenUpListener){
wakenUpListeners.add(wakenUpListener);
}
//提供一个通知方法
public void wakeUp(){
for (int i=0;i<wakenUpListeners.size();i++){
WakenUpEvent wakenUpEvent = new WakenUpEvent(111111L,"111111",this);
wakenUpListeners.get(i).actionToWakenUp(new WakenUpEvent(1111L,"1111",this));
}
}
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
wakeUp();
}
}
定义Test类
package observersOOD.Listener;
public class Test {
public static void main(String[] args) {
WakenUpListener dad = new Dad();
WakenUpListener grandFather = new GrandFather();
Child child = new Child();
child.addWakenUpListener(dad);
child.addWakenUpListener(grandFather);
Thread thread = new Thread(child);
thread.start();
}
}
运行结果
1111
1111
开始喂孩子....
抱孩子......