1,观察者模式
观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。
又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
2,观察者模式角色
-
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
-
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
-
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
3,观察者模式 Demo
1,抽象观察者
package com.demo.base.design_partten.observer;
/**
* 观察者
* */
public interface Observer {
/*
* 订阅内容,接收订阅内容
* */
public void attachMsg(String subject, String msg);
}
2,抽象主题
package com.demo.base.design_partten.observer;
/**
* 主题
* @author admin
* */
public interface Subject {
/**
* 添加观察者
* */
public void attach(Observer observer);
/**
* 发布消息
* */
public void notify(String msg);
/**
* 移除观察者
* */
public void detach(Observer observer);
}
3,观察者实现
package com.demo.base.design_partten.observer;
/**
* 观察者实例
* */
public class ConcreteObserver implements Observer {
String name;
@Override
public void attachMsg(String subject, String msg) {
System.out.println(String.format("观察者:%s 收到 %s 发布的消息:%s", name, subject, msg));
//doSth...
}
public ConcreteObserver(){}
public ConcreteObserver(String name){
this.name = name;
}
}
4,主题实现
package com.demo.base.design_partten.observer;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* 主题实现类
* */
public class ConcreteSubject implements Subject{
/**
* 观察者集合
* */
private Set<Observer> events = new LinkedHashSet<>();
//主题名称
String name;
@Override
public void attach(Observer observer) {
events.add(observer);
}
@Override
public void notify(String msg) {
for(Observer observer : events){
observer.attachMsg(name, msg);
}
}
@Override
public void detach(Observer observe) {
events.remove(observe);
}
public ConcreteSubject(){}
public ConcreteSubject(String name){
this.name = name;
}
}
5,业务类
package com.demo.base.design_partten.observer;
/**
* 观察者模式:
* 1,观察者接口
* 定义订阅方法,用来接收发布的消息
* 2,观察者实现类
* 实现订阅方法,接收发布的消息
* 3,主题接口 subject
* 定义了添加观察者,删除观察者,发布消息三个接口
* 4,主题实现类 ConcreteSubject
* 内部持有一个观察者结合,实现发布消息接口,发布消息时候循环调用观察者订阅方法。
* 5,测试方法
* 观察者订阅主题,调用主题的 attach 方法。
* 主题发布消息,会通知所有观察者
*
* */
public class MainTest {
public static void main(String[] args) {
ConcreteObserver c1 = new ConcreteObserver("小明");
ConcreteObserver c2 = new ConcreteObserver("小李");
ConcreteObserver c3 = new ConcreteObserver("小张");
ConcreteSubject bos = new ConcreteSubject("老板");
bos.attach(c1);
bos.attach(c2);
bos.attach(c3);
bos.attach(c1);
ConcreteSubject s = new ConcreteSubject("家长");
s.attach(c1);
s.attach(c2);
s.attach(c3);
s.notify("啥时候回来啊");
bos.notify("国庆都给我加班!");
}
}
4,发布-订阅模式
相比观察者模式多了订阅中心。
1,发布者
package com.demo.base.design_partten.observer.publish_subscrice;
/**
* 发布者
* @author
* */
public class Publisher {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Publisher(){}
public Publisher(String name){
this.name = name;
}
}
2,订阅者
package com.demo.base.design_partten.observer.publish_subscrice;
/**
* 订阅者
* @author admin
*/
public class SubScriber {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SubScriber(){}
public SubScriber(String name){
this.name = name;
}
public void getMessage(Publisher publisher, String msg){
System.out.println(String.format( "订阅者:%s 收到 %s 发布的消息:%s!", name, publisher.getName(), msg) );
}
}
3,订阅中心接口
package com.demo.base.design_partten.observer.publish_subscrice;
/**
* @author admin
* 订阅中心
*/
public interface PublisherCentral {
//添加发布者-订阅者
public void addPublisher(Publisher publisher, SubScriber... subScriber);
//删除发布者-订阅者
public void removePublisher(Publisher publisher, SubScriber ... subScribers);
//发布消息
public void publishMsg(Publisher publisher, String msg);
}
4,订阅中心实现
package com.demo.base.design_partten.observer.publish_subscrice;
import java.util.*;
/**
* @author admin
*/
public class PublisherCentralImpl implements PublisherCentral {
private Map<Publisher, Set<SubScriber>> set = new HashMap<>();
private String name;
public PublisherCentralImpl(){}
public PublisherCentralImpl(String name){
this.name = name;
}
@Override
public void addPublisher(Publisher publisher, SubScriber... subScriber) {
Set<SubScriber> s = set.get(publisher);
if(s == null){
s = new LinkedHashSet<>(Arrays.asList(subScriber));
set.put(publisher, s);
}else{
s.addAll(Arrays.asList(subScriber));
}
}
@Override
public void removePublisher(Publisher publisher, SubScriber... subScribers) {
Set<SubScriber> s = set.get(publisher);
if(s == null){
return;
}else{
s.removeAll(Arrays.asList(subScribers));
}
}
@Override
public void publishMsg(Publisher publisher, String msg) {
Set<SubScriber> s = set.get(publisher);
System.out.println(String.format("%s 在 %s 发布了消息:%s", publisher.getName(), name, msg));
if(s != null){
for(SubScriber subScriber : s){
subScriber.getMessage(publisher, msg);
}
}
}
}
5,业务类
package com.demo.base.design_partten.observer.publish_subscrice;
/**
* @author 发布-订阅模式
*/
public class MainTest {
public static void main(String[] args) {
//订阅中心
PublisherCentral publisherCentral = new PublisherCentralImpl("报社一");
Publisher p1 = new Publisher("大河网");
Publisher p2 = new Publisher("河南网");
Publisher p3 = new Publisher("东京网");
publisherCentral.addPublisher(p1, new SubScriber("张三"), new SubScriber("李四"), new SubScriber("王五"));
publisherCentral.addPublisher(p2, new SubScriber("张三"), new SubScriber("小六"));
publisherCentral.addPublisher(p3, new SubScriber("join"));
publisherCentral.publishMsg(p1, "大河网最新报道!");
publisherCentral.publishMsg(p2, "今年还行!");
publisherCentral.publishMsg(p3, "bird language!");
}
}
标签:String,Observer,void,观察者,模式,new,public,name
From: https://www.cnblogs.com/cnff/p/17274692.html