观察者模式

文章目录
  1. 1. 观察者模式
  2. 2. jdk中观察者模式的实现
观察者模式

可以通过jdk中提供的Observable类和Observer接口来实现观察者模式。下面通过简单的会员订阅频道,然后频道定期的去给订阅的会员推送消息,展示jdk中观察者模式的使用。

/**
* @Author long
* @Date 2019/9/13 9:16
*/
public class App {
public static void main(String[] args) {
// 科技频道
TechnologyChannel technologyChannel = new TechnologyChannel();
technologyChannel.setTitle("科技频道");
// 用户
Members member1 = new Members();
Members member2 = new Members();
// 用户订阅该科技频道
technologyChannel.addObserver(member1);
technologyChannel.addObserver(member2);
// 给会员定时推送消息
String[] messages = {"华为", "小米", "苹果"};
Random random = new Random();
for (int i = 0; i < 10 ; i++) {
// 创建消息
NotifyMessage message = new NotifyMessage();
String id = UUID.randomUUID().toString();
message.setId(id);
message.setCreateTime(System.currentTimeMillis());
message.setTitle("手机");
message.setContent(messages[random.nextInt(3)] + "又出新机,赶快来订购吧!");
// 评到发送消息给订阅的会员
technologyChannel.setChanged();
technologyChannel.notifyObservers(message);
try {
TimeUnit.MILLISECONDS.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

/**
* @Author long
* @Date 2019/9/13 9:14
* 频道
*/
@Data
public class TechnologyChannel extends Observable {
private String title;

public synchronized void setChanged() {
super.setChanged();
}
}

/**
* @Author long
* @Date 2019/9/13 9:13
* 会员
*/
public class Members implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof TechnologyChannel) {
TechnologyChannel channel = (TechnologyChannel)o;
String title = channel.getTitle();
NotifyMessage message = (NotifyMessage)arg;
System.out.println("channel:" + title);
System.out.println("message:" + message);
System.out.println("=======================");
}
}
}
/**
* @Author long
* @Date 2019/9/13 9:28
* 消息通知
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NotifyMessage implements Serializable {

private String id;
private Long createTime;
private String title;
private String content;
}
jdk中观察者模式的实现
  1. 观察者(类似订阅模式中的订阅者)。jdk中定义了一个公共的接口Observer,里面定义了一个update方法,该方法可以接收被观察者对象和一个参数对象。我们可以通过实现该接口,重写update方法来实现观察者的逻辑。
  2. 被观察者(类似订阅模式中的被订阅者)。jdk中定义了一个类Observable,可以实现添加,移除,通知观察者。该类里面有两个属性boolean:changedVector:obs。当我们执行addObserver方法来添加观察者时,若是该观察者还未被加入到Vector:obs中,会将观察者加入到该集合。当我们执行notifyObservers方法来通知观察者时,只有changed属性为true时,才会依次调用观察者的update方法。若是该值为true,在调用观察者的update方法之前,又会将该值设置为false
public interface Observer {
void update(Observable o, Object arg);
}
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;

public Observable() {
obs = new Vector<>();
}

// 添加观察者
public synchronized void addObserver(Observer o) {
if (o == null) {
throw new NullPointerException();
}
if (!obs.contains(o)) {
obs.addElement(o);
}
}

// 通知所有的观察者,可以传递一个参数
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
// 若是状态未变化,不做任何事情
if (!changed) {
return;
}
// 将Vector转化为一个数组
arrLocal = obs.toArray();
// 将changed设置为false
clearChanged();
}
// 循环遍历Observer数组,调用其update方法
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
}