《Head Fisrt》里面和各个论坛都喜欢用天气预报板块举例,个人不太理解那个场景;
这里用朋友圈的女神举例:女神自然有一堆关注者,每次她的状态一更新,其跟随者各种大开脑洞为博女神眼球。这里使用观察者模式实现;
package com.git.poan.designparttern;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
// 1. 将女神的状态发布抽象为接口
interface GoddessFollower {
void post(PostType type);
}
// 2. 将女神的状态类型使用枚举列举处理
enum PostType {
Image(1, "自拍"),
Voice(2, "语音"),
Video(3, "视频"),;
private final int value;
public final String content;
PostType(int value, String content) {
this.value = value;
this.content = content;
}
}
// 3. 女神的跟随者实现状态发布接口,并对`2`中的各种状态做对应处理
class Diaosi implements GoddessFollower {
@Override
public void post(PostType type) {
switch (type) {
case Image:
System.out.println("Diaosi评价:好看!");
break;
case Video:
System.out.println("Diaosi评价:好美!赞一个");
break;
case Voice:
System.out.println("Diaosi评价:好听!赞一个");
}
}
}
// 3. 女神的跟随者实现状态发布接口,并对`2`中的各种状态做对应处理
class FuShuai implements GoddessFollower {
@Override
public void post(PostType type) {
switch (type) {
case Image:
System.out.println("FuShuai评价:小姐姐有空么?");
break;
case Video:
System.out.println("FuShuai评价:小姐姐有空么?");
break;
case Voice:
System.out.println("FuShuai评价:小姐姐有空么?");
}
}
}
// 4. 由票圈PiaoCircle来统一调用
public class PiaoCircle {
private List<GoddessFollower> goddessesFollowers = new ArrayList<>();
public void addFollower(GoddessFollower goddessesFollower) {
goddessesFollowers.add(goddessesFollower);
}
public void remove(GoddessFollower goddessesFollower) {
goddessesFollowers.remove(goddessesFollower);
}
public void timePass() {
PostType[] values = PostType.values();
Random random = new Random();
int i = random.nextInt(values.length - 1);
PostType postType = values[i];
System.out.println("女神发表了" + postType.content);
for (GoddessFollower goddessesFollower : goddessesFollowers) {
goddessesFollower.post(postType);
}
}
public static void main(String[] args) {
PiaoCircle piaoCircle = new PiaoCircle();
System.out.println("====================Diaosi关注了女神====================");
Diaosi diaosi = new Diaosi();
piaoCircle.addFollower(diaosi);
piaoCircle.timePass();
System.out.println("====================FuShuai关注了女神======================");
piaoCircle.addFollower(new FuShuai());
piaoCircle.timePass();
System.out.println("====================Diaosi取消关注了女神====================");
piaoCircle.remove(diaosi);
piaoCircle.timePass();
}
}
2
中的各种状态做对应处理观察者模式,观察的对象状态变化非常频繁,可以将goddessesFollowers替换为CopyOnWriteArrayList,可以保证新关注者,不会由于竞态发生误操作;
在实际业务中,会比以上场景复杂,当观察的对象状态发生变化不会仅仅只是打印一句话,比如原本只有3个观察者需要对观察到的状态对自己业务做CRUD时,新来了一个观察者…… 那么这个观察者就会误操作……
其实以上的问题在于,新添加的观察者,不能看到被观察状态改变之前操作,这里可以用CopyOnWriteArrayList替换List实现~ 原因在于CopyOnWriteArrayList是一个在写操作时,会创建一个新的List,不干扰之前的结构,在写入过程中入如果有读操作,则会读取到之前的结构;这样就保证了竞态下观察者模式的线程安全问题。
你看那个人好像一条狗啊