在Observer模式中,当观察对象的状态发生变化时,会通知给观察者模式。Observer模式适用于根据对象状态进行相应处理的场景。
示例程序
观察者将观察一个会生成数值的对象,并将它生成的数值结果显示出来。不过,不同的观察者的显示方式不一样,DigitObserver会以数字形式显示数值,GrphaObserver则会以简单的图示形式来显示数值。
Observer接口
该接口是观察者的接口,具体的观察者会实现这个接口。
用于生成数值的NumberGenerator类会调用update方法。如果调用update方法,NumberGenerator方法就会将“生成的数值发生了变化,请更新显示内容”的通知发送给Observer。
package Observer;
public interface Observer {
public abstract void update(NumberGenerator generator);
}
NumberGenerator类
该类是用于生成数值的抽象类,生成数值的方法和获取数值的方法都是抽象方法,需要子类去实现。
package Observer;
import java.util.ArrayList;
import java.util.Iterator;
public abstract class NumberGenerator {
private ArrayList observers = new ArrayList();
public void addObserver(Observer observer){
observers.add(observer);
}
public void deleteObserver(Observer observer){
observers.remove(observer);
}
public void notifyObserver(){
Iterator it = observers.iterator();
while(it.hasNext()){
Observer o = (Observer)it.next();
o.update(this);
}
}
public abstract int getNumber();
public abstract void execute();
}
RandomNumberGenerator类
该类是NumberObserver的子类,它会生成随机数。
package Observer;
import java.util.Random;
public class RandomNumberGenerator extends NumberGenerator {
private Random random = new Random();
private int number;
@Override
public int getNumber() {
// TODO Auto-generated method stub
return number;
}
@Override
public void execute() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
number = random.nextInt(50);
notifyObserver();
}
}
}
DigitObserver类
该类实现了Observer接口,它的功能是以数字形式显示数值。
package Observer;
public class DigitObserver implements Observer {
@Override
public void update(NumberGenerator generator) {
// TODO Auto-generated method stub
System.out.println("DigitObserver:"+generator.getNumber());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
GraphaObserver类
该类也实现了Observer接口,会将数值以简单图示的形式显示出来。
package Observer;
public class GraphaObserver implements Observer {
@Override
public void update(NumberGenerator generator) {
// TODO Auto-generated method stub
System.out.print("GraphaObserver:");
int count = generator.getNumber();
for(int i=0;i<count;i++){
System.out.print("*");
}
System.out.println("");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
Main类
package Observer;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
// NumberGenerator generator = new RandomNumberGenerator();
// Observer obj1 = new DigitObserver();
// Observer obj2 = new GraphaObserver();
// generator.addObserver(obj1);
// generator.addObserver(obj2);
// generator.execute();
NumberGenerator generator = new IncreamelNumber(10,50,5);
Observer obj1 = new DigitObserver();
Observer obj2 = new GraphaObserver();
generator.addObserver(obj1);
generator.addObserver(obj2);
generator.execute();
}
}
练习
编写IncreamelNumber类,继承NumberGenerator类,使其具有数值递增的功能。
package Observer;
public class IncreamelNumber extends NumberGenerator {
private int start;
private int end;
private int step;
private int number;
public IncreamelNumber(int start,int end,int step) {
// TODO Auto-generated constructor stub
this.start = start;
this.end = end;
this.step = step;
}
@Override
public int getNumber() {
// TODO Auto-generated method stub
return number;
}
@Override
public void execute() {
// TODO Auto-generated method stub
for(int i = start;i<end;i+=step){
number = i;
notifyObserver();
}
}
}
可替换性的设计思想:
- 利用抽象类和接口从具体类中抽出抽象方法
- 在将实例作为参数传递至类中,或者在类的字段中保存实例时,不使用具体类型,而是使用抽象类型和接口。