观察者模式定义了一套机制,可以实现一对多的关系,当“一”(被观察者)的状态发生了变化,会通知“多”个(观察者),这是行为型模式。
这个模式存在这样的一个问题:如果由观察者不停地查询被观察者的状态变化,那么观察者将苦不堪言;而如果由被观察者来通知所有的观察者,那么有些对该状态不感兴趣的观察者将会“抱怨”。
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class HexObserver extends Observer {
public HexObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Hex string: " + subject.getState());
}
}
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Octal string: " + subject.getState());
}
}
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Binary string: " + subject.getState());
}
}
public class Subject {
private int state;
private List<Observer> observers = new ArrayList<>();
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer o : observers) {
o.update();
}
}
}
public class Client {
public static void main(String[] args) {
Subject subject = new Subject();
new HexObserver(subject);
new BinaryObserver(subject);
new OctalObserver(subject);
System.out.println("First state changes: 111");
subject.setState(111);
System.out.println("--------------------------");
System.out.println("Second state changes: 222");
subject.setState(222);
}
}
First state changes: 111
Hex string: 111
Binary string: 111
Octal string: 111
--------------------------
Second state changes: 222
Hex string: 222
Binary string: 222
Octal string: 222
Process finished with exit code 0
public class Publisher {
public Publisher(Integer pubId) {
this.pubId = pubId;
}
private Integer pubId;
public Integer getPubId() {
return pubId;
}
public void setPubId(Integer pubId) {
this.pubId = pubId;
}
@Override
public String toString() {
return "Publisher{" +
"pubId=" + pubId +
'}';
}
}
public class Subscriber {
public Subscriber(Integer subId) {
this.subId = subId;
}
private Integer subId;
public Integer getSubId() {
return subId;
}
public void setSubId(Integer subId) {
this.subId = subId;
}
@Override
public String toString() {
return "Subscriber{" +
"subId=" + subId +
'}';
}
}
public class Message {
public Message(String content) {
this.content = content;
}
private String content;
@Override
public String toString() {
return "Message{" +
"content='" + content + '\'' +
'}';
}
}
public interface SubPubCentral {
boolean subscribe(Publisher publisher, Subscriber subscriber);
boolean unsubscribe(Publisher publisher, Subscriber subscriber);
void publish(Publisher publisher, Message message);
}
public class SubPubCentralImpl implements SubPubCentral {
private static Map<Integer, Set<Integer>> pubSubMap;
static {
pubSubMap = new HashMap<>();
}
@Override
public boolean subscribe(Publisher publisher, Subscriber subscriber) {
Set<Integer> subscribeSet = pubSubMap.getOrDefault(publisher.getPubId(), new HashSet<>());
boolean add = subscribeSet.add(subscriber.getSubId());
if (add) pubSubMap.put(publisher.getPubId(), subscribeSet);
return pubSubMap.size() > 0;
}
@Override
public boolean unsubscribe(Publisher publisher, Subscriber subscriber) {
Set<Integer> subscribeSet = pubSubMap.get((publisher.getPubId()));
boolean remove = false;
if (subscribeSet != null && subscribeSet.size() > 0) {
remove = subscribeSet.remove(subscriber.getSubId());
if (remove) pubSubMap.put(publisher.getPubId(), subscribeSet);
}
return remove;
}
@Override
public void publish(Publisher publisher, Message message) {
Set<Integer> subscribeSet = pubSubMap.get((publisher.getPubId()));
for (Integer id : subscribeSet) {
System.out.println("向发布者[" + publisher.getPubId() + "]的订阅者[" + id + "]发送消息:" + message);
}
}
}
public class PublisherController {
private SubPubCentral subPubCentral;
public PublisherController(SubPubCentral subPubCentral) {
this.subPubCentral = subPubCentral;
}
public void publish(Integer pubId, String message) {
subPubCentral.publish(new Publisher(pubId), new Message(message));
}
}
public class SubscribeController {
private SubPubCentral subPubCentral;
public SubscribeController(SubPubCentral subPubCentral) {
this.subPubCentral = subPubCentral;
}
public void sub(Integer subId, Integer pubId) {
subPubCentral.subscribe(new Publisher(pubId), new Subscriber(subId));
}
public void unsub(Integer subId, Integer pubId) {
subPubCentral.unsubscribe(new Publisher(pubId), new Subscriber(subId));
}
}
public class Client {
public static void main(String[] args) {
SubPubCentral subPubCentral = new SubPubCentralImpl();
PublisherController publisherController = new PublisherController(subPubCentral);
SubscribeController subscribeController = new SubscribeController(subPubCentral);
subscribeController.sub(100, 001);
subscribeController.sub(101, 001);
publisherController.publish(001, "from#001 publish, COVID-19 regions of high risk");
System.out.println("~~~~~~~~~~~~~~~~~~");
subscribeController.unsub(100, 001);
publisherController.publish(100, "$$%%$$");
}
}
- https://blog.csdn.net/David_TD/article/details/107715396
- https://embeddedartistry.com/fieldatlas/differentiating-observer-and-publish-subscribe-patterns/
- https://www.runoob.com/design-pattern/observer-pattern.html
- https://refactoring.guru/design-patterns/observer