java订阅发布案例,结合观察者模式
应用场景:
用java写一个服务端程序,可以接受订阅和取消订阅,或拉取,和主动推送。初步一想,似乎很简单,但做成容易扩展和类似框架结构,就没那么随意设计了。当然,本人也是个新手,阅读了设计模式一书中的观察者模式,不断写一些小demo,为了充分理解面向接口面层,也是从定义顶层接口入手了。
功能说明:
贴测试类代码了。注释很明白了。
public static void main(String[] args) { //init register //1.currentTObserver,displyTObserver两个观察者(客户端)。 CurrentTObserver currentTObserver=new CurrentTObserver("CurObserver1"); DisplyTObserver displyTObserver=new DisplyTObserver("DisObserver"); //2.两个观察者(客户端)订阅了不同类型,品种的数据。currentTObserver订阅了两种个容器的数据,另外一个只订阅了天气容器中的数据。 WeatherSubjectContainer.getInstance().registerObserver(currentTObserver); WeatherSubjectContainer.getInstance().registerObserver(displyTObserver); CarSubjectContainer.getInstance().registerObserver(currentTObserver); //3.WeatherSubjectContainer和CarSubjectContainer两种数据发生了改变的时候,调用自己的dateChange方法,两个客户端就可以收到对应数据了。 //4.扩展数据品种增加一个container,增加一种数据类型即可。 int te = 1; int hum = 3; while (true) { try { Thread.sleep(1000); System.out.println(" data rescore push data ..."); te++; hum++; WeaterDate weaterDate = new WeaterDate("WD_DATA"); weaterDate.setTemperature(te); weaterDate.setHumidity(hum); WeatherSubjectContainer.getInstance().dateChange(weaterDate); CarDate carDate = new CarDate("CAR_DATA"); carDate.setCarNum("CarA0000"); carDate.setCarStatus("空"); CarSubjectContainer.getInstance().dateChange(carDate); //模拟取消订阅 if (te>5){ WeatherSubjectContainer.getInstance().rmoveObserver(currentTObserver); } System.out.println("WE->"+WeatherSubjectContainer.getInstance().getMapSize()); System.out.println("Cr->"+CarSubjectContainer.getInstance().getMapSize()); } catch (InterruptedException e) { e.printStackTrace(); } } }
1.项目结构:
2.结构说明:
core包中包括两个顶层接口,一个主题抽象类,数据的抽象类,基类,观察者的基类。所有的相关的新写的对象都要继承或实现其中的特有方法。model包中定义数据具体类,继承BaseDate,observer包中是所有观察者,自己定义,需要继承BaseTobserver类。subject包中就是数据容器了。数据添加进容器不在这里讨论了。
3.核心如下代码:其中没使用到的方法和接口中的内容是为了扩展应用。实际是用不到可以削减方法。后面的subject和model,就看实际业务数据怎么样就怎么写了。做好继承就行。观察者的话,接收到数据分类处理即可。
public abstract class BaseDate { private String dataId; public BaseDate(String dataId) { this.dataId = dataId; } public String getDataId() { return dataId; } public void setDataId(String dataId) { this.dataId = dataId; } }
public abstract class BaseToserver implements TObserver { private String observerId; public BaseToserver(String observerId) { this.observerId = observerId; } public abstract void update(BaseDate baseDate); public abstract void init(BaseDate baseDate); public String getObserverId() { return observerId; } public void setObserverId(String observerId) { this.observerId = observerId; } }
public abstract class Subject implements TObservable { public static Logger LOG = LoggerFactory.getLogger(Subject.class); private BaseDate data; private ConcurrentHashMap<String, BaseToserver> submap = new ConcurrentHashMap<>(); @Override public void registerObserver(BaseToserver o) { submap.put(o.getObserverId(), o); } @Override public void rmoveObserver(BaseToserver o) { if (submap.containsKey(o.getObserverId())) { submap.remove(o.getObserverId()); } else { LOG.error(" remove failed " + o.getObserverId()); } } @Override public void notifyObsevers() { Set<Map.Entry<String, BaseToserver>> entrySet = submap.entrySet(); for (Map.Entry<String, BaseToserver> entry : entrySet ) { entry.getValue().update(data); } } @Override public void dateChange(BaseDate o) { this.data = o; notifyObsevers(); } public int getMapSize() { return submap.size(); } }
public interface TObservable { public void registerObserver(BaseToserver o); public void rmoveObserver(BaseToserver o); public void notifyObsevers(); public void dateChange(BaseDate o); }
public interface TObserver<T> { public void TestHandle(); }
public class CarDate extends BaseDate{ public CarDate(String dateId) { super(dateId); } private String carNum; private String carStatus; public String getCarNum() { return carNum; } public void setCarNum(String carNum) { this.carNum = carNum; } public String getCarStatus() { return carStatus; } public void setCarStatus(String carStatus) { this.carStatus = carStatus; } }
public class CurrentTObserver extends BaseToserver { public CurrentTObserver(String observerId) { super(observerId); } @Override public void update(BaseDate baseDate) { if (baseDate instanceof WeaterDate) { WeaterDate date = (WeaterDate) baseDate; System.out.println(" Current observer receive WeaterDate-> " + date.getHumidity() + "-" + date.getTemperature()); } else if (baseDate instanceof CarDate) { CarDate carDate = (CarDate) baseDate; System.out.println(" Current observer receive carDate> " + carDate.getCarNum() + "-" + carDate.getCarStatus()); } } @Override public void init(BaseDate BaseDate) { } @Override public void TestHandle() { } }
public class CarSubjectContainer extends Subject{ private static WeatherSubjectContainer ourInstance = new WeatherSubjectContainer(); public static WeatherSubjectContainer getInstance() { return ourInstance; } }
4.总结:根据设计模式和合理使用抽象类的编程设计,还是第一次从这种角度去考虑。感觉很不错。模型有了,解读源码和框架就更舒服了。观察者和数据类型完整代码资料下载地址:https://download.****.net/download/flybridy/10460374