《设计模式》--发布订阅模式
发布订阅模式
该模式主要涉及三个类型对象: 发布者、发布订阅管理器、订阅者;
设计原理
发布者将消息发布到管理器上, 订阅者从管理器订阅消息;这样将发布者和订阅者进行了解耦,实现了松耦合;
实现代码实例
1、发布者
package com.jt.designModel.subscriber;
public class PublisherImpOne<T> implements Ipublisher<T> {
private String name;
public PublisherImpOne(String name) {
super();
this.name = name;
}
@Override
public void publish(SubscribePublish<T> subscribePublish, T message, boolean isInstantMsg) {
subscribePublish.publish(this.name, message, isInstantMsg);
}
}
2、管理器
package com.jt.designModel.subscriber;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class SubscribePublish<T> {
//订阅器名称
private String name;
//订阅器队列容量
final int QUEUE_CAPACITY = 20;
//订阅器存储队列
private BlockingQueue<Msg<T>> queue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
//订阅者
private List<ISubcriber<T>> subcribers = new ArrayList<>();
public SubscribePublish(String name) {
this.name = name;
}
public void publish(String publisher, T message, boolean isInstantMsg) {
//true
if (isInstantMsg) {
update(publisher, message);
return;
}
Msg<T> m = new Msg<T>(publisher, message);
if (!queue.offer(m)) {
update();
}
}
public void subcribe(ISubcriber<T> subcriber) {
subcribers.add(subcriber);
}
public void unSubcribe(ISubcriber<T> subcriber) {
subcribers.remove(subcriber);
}
public void update() {
Msg<T> m = null;
while ((m = queue.peek()) != null) {
this.update(m.getPublisher(), (T) m.getMsg());
}
}
public void update(String publisher, T Msg) {
for (ISubcriber<T> subcriber : subcribers) {
subcriber.update(publisher, Msg);
}
}
}
class Msg<T> {
private String publisher;
private T m;
public Msg(String publisher, T m) {
this.publisher = publisher;
this.m = m;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public T getMsg() {
return m;
}
public void setMsg(T m) {
this.m = m;
}
}
3、订阅者
package com.jt.designModel.subscriber;
public class SubcriberImpOne<T> implements ISubcriber<T> {
public String name;
public SubcriberImpOne(String name) {
super();
this.name = name;
}
@Override
public void subcribe(SubscribePublish<T> subscribePublish) {
subscribePublish.subcribe(this);
}@Override
public void unSubcribe(SubscribePublish<T> subscribePublish) {
subscribePublish.unSubcribe(this);
}@Override
public void update(String publisher, T message) {
System.out.println(this.name + "收到" + publisher + "发来的消息:" + message.toString());
}}
4、测试类
package com.jt.designModel.subscriber;
public class Test {
public static void main(String[] args) {
SubscribePublish<String> subscribePublish = new SubscribePublish<String>("订阅器");
Ipublisher<String> publisher1 = new PublisherImpOne<>("发布者1");
Ipublisher<String> publisher2 = new PublisherImpOne<>("发布者2");ISubcriber<String> subcriber = new SubcriberImpOne<String>("订阅者1");
subcriber.subcribe(subscribePublish);
// 发布消息
publisher1.publish(subscribePublish, "welcome", true);
publisher1.publish(subscribePublish, "to", true);
publisher2.publish(subscribePublish, "你好", true);
}}
5、测试结果
订阅者1收到发布者1发来的消息:welcome
订阅者1收到发布者1发来的消息:to
订阅者1收到发布者2发来的消息:你好
总结
发布订阅模式, 主要是通过订阅器达到和发布者之间的松耦合关系;该模式可用在消息推送类型的场景;在我所在的项目中, 由于数据库表存在冗余的消息, 在更新基础表信息时,需要将冗余的信息同步更改。 也可以采用该模式;在分布式项目中,也可以采用消息中间件 来实现多个项目的一致性。
该模式和观察者模式之间的区别, 主要的区别就在于,是否存在 管理器;观察者模式中, 观察者和发布者之间存在耦合, 即观察者需要注册到发布者对象上, 这样,发布者在发布时, 会执行观察者的相应方法;下图借助于网上,能够比较清晰的区分这两种模式的区别: