前言
訂閱發佈最常見的就是在公衆號的訂閱,用戶訂閱了公衆號後,公衆號發佈消息時就能收到。其實他相當於設計模式中的觀察者模式
大致流程圖
用戶首先對感興趣的服務進行訂閱,該服務在發送消息時會將消息發送至所有訂閱的用戶。
實現
接口定義
使用java實現的版本
首先定義下接口,再對其進行實現。
public interface Service {
boolean addSubscribe(Observice observice); // 增加訂閱者
boolean removeSubscribe(Observice observice); // 刪除訂閱者
void push(Object o); // 推送消息
}
這是一個服務的接口,聲明瞭3個主要的方法,分別是增加訂閱,刪除訂閱,以及推送消息。
public interface Observice {
void gotIt(Object s); // 收到消息後的動作
String getId();
String getName();
}
這個接口用來作爲用戶的接口,提供獲取Id,name以及消息訂閱後的動作。
接口實現
下面是消息服務的實現,在收到訂閱後根據id放到map裏,然後根據id刪除。
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MessageService implements Service {
private static Map<String,Observice> observerMap = new ConcurrentHashMap<>();
@Override
public boolean addSubscribe(final Observice observice) {
observerMap.put(observice.getId(),observice);
System.out.println(String.format("用戶Id %s 姓名 %s 插入成功 ", observice.getId(), observice.getName()));
return true;
}
@Override
public boolean removeSubscribe(final Observice observice) {
if (observerMap.get(observice.getId()) == null){
System.out.println(String.format("用戶Id %s 姓名 %s 不存在 移除失敗", observice.getId(), observice.getName()));
return false;
}
observerMap.remove(observice.getId());
System.out.println(String.format("用戶Id %s 姓名 %s 已經移除 ", observice.getId(), observice.getName()));
return true;
}
@Override
public synchronized void push(Object S) {
if (null == S) return;
observerMap.forEach((k,v)-> v.gotIt(S));// 推送時採用輪訓推送
System.out.println("所有消息推送完畢");
}
下面是用戶接口的實現,在收到消息後只是簡單的打印了出來
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class VipUser implements Observice {
private String id;
private String username;
@Override
public void gotIt(Object s) {
System.out.print("收到了推送:\t");
System.out.println(s);
}
@Override
public String getId() {
return this.id;
}
@Override
public String getName() {
return this.username;
}
}
測試
在編寫完後對整個流程進行測試
public static void main(String[] args) {
Service service = new MessageService();
Observice user1 = new VipUser("1","小李");
Observice user2 = new VipUser("2","小王");
Observice user3 = new VipUser("3","小張");
// 每個用戶都進行訂閱
service.addSubscribe(user1);
service.addSubscribe(user2);
service.addSubscribe(user3);
service.push("大家好,這是第一條推送");// 推送消息
service.removeSubscribe(user2);
service.removeSubscribe(user2);// 移除兩次,會提示移除失敗。
service.push("大家好,這條推送沒小王");
}
結果如下
用戶Id 1 姓名 小李 插入成功
用戶Id 2 姓名 小王 插入成功
用戶Id 3 姓名 小張 插入成功
收到了推送: 大家好,這是第一條推送
收到了推送: 大家好,這是第一條推送
收到了推送: 大家好,這是第一條推送
所有消息推送完畢
用戶Id 2 姓名 小王 已經移除
用戶Id 2 姓名 小王 不存在 移除失敗
收到了推送: 大家好,這條推送沒小王
收到了推送: 大家好,這條推送沒小王
所有消息推送完畢
小結
通過這個小栗子可以初步的瞭解這種模式的設計,這樣可以使用戶和服務進行鬆耦合,用戶可以隨意的選擇服務進行訂閱,消息也可以精準的推送。
以下是代碼存放的地址,沒幾個文件,萌新們可以一起來學習下。 [項目Demo地址](https://github.com/zza1998/java-mac/tree/master/src/main/java/com/zza/subscribe)