Archetype&Specification&Publish-Subscribe
2015-09-23 18:03
351 查看
转载自:http://blog.csdn.net/m13666368773/article/details/7472126
http://blog.csdn.net/m13666368773/article/details/7472140
http://blog.csdn.net/m13666368773/article/details/7472157
假设系统中有一个记录各种事件的接口:
EventRecorder.java
EventRecorderDelegate.java
ComplicateEventRecorder.java
在Specification设计模式中,一个条件就是一个specification,多个specification通过串联的方式以某种逻辑关系形成一个组合式的specification。首先看一下整体的UML图:
下面是Specification接口的声明:
下面来看CompositSpecification的声明:
先定义一个男人:
Subscribe机制是个不错的选择,它的耦合性低,各个参与者之间毫无关联。每 一个消息都有一个唯一标识,一般都用字符串来描述,比如用户管理模块中新添加了一个用户,于是它发送了一个消息:/User/Add,消息的其他信息可以放置到一个Map中。下面是一个最简单的消息订阅接口:
下面消息发送的实现类:
测试示例:
ASubscriber订阅“/User/Add”的内容,BSubscriber订阅“/User/Del”的内容。当messagePublisher发布时消息时,订阅该消息的将会执行onRecived()方法。
http://blog.csdn.net/m13666368773/article/details/7472140
http://blog.csdn.net/m13666368773/article/details/7472157
Archetype
Archetype设计模式的目的是将业务处理逻辑和具体实现分离,所以至少需要两个参与者:Decorator和Delegate,它们都实现同一个接口,Decorator负责处理业务逻辑,而Delegate负责具体的实现,在Decorator的通用业务逻辑处理过程中,会把具体实现委派给Delegate。假设系统中有一个记录各种事件的接口:
EventRecorder.java
public interface EventRecorder { // 记录事件的内容 public void record(String event); }引入两个抽象类来达到处理逻辑和具体实现分离的目的:
EventRecorderDelegate.java
public abstract class EventRecorderDelegate implements EventRecorder { }EventRecorderDecorator.java
public abstract class EventRecorderDecorator implements EventRecorder { protected EventRecorderDelegate delegate; public void setDelegate(EventRecorderDelegate delegate) { this.delegate = delegate; } }下面是两个简单的逻辑处理(Decorator)类:
ComplicateEventRecorder.java
public class ComplicateEventRecorder extends EventRecorderDecorator{ public void record(String event){ // 附加当前的日期到事件的内容中 event = System.currentTimeMillis() + event; // 附加当前异常信息到事件的内容中 // 附加当前的env event = event+System.getenv(); // 记录事件的内容 delegate.record(event); } }SimpleEventRecorder.java
public class SimpleEventRecorder extends EventRecorderDecorator { public void record(String event) { // 附加当前的日期到事件的内容中 event = System.currentTimeMillis() + event; // 记录事件的内容 delegate.record(event); } }最后一步都交给了EventRecorderDelegate对象,这一步就是之前所说的“具体实现”:
public class RecordEventToDatabase extends EventRecorderDelegate { public void record(String event) { // 将记录写入到数据库中 } }
public class RecordEventToFile extends EventRecorderDelegate { public void record(String event) { // 将记录写入到文件中 } }下面是一个生成事件记录对象的工厂:
public class EventRecorderFactory { public static EventRecorder create(int type, int flag) { EventRecorderDelegate delegate = null; EventRecorderDecorator decorator = null; if (type == 0) decorator = new SimpleEventRecorder(); if (type == 1) decorator = new ComplicateEventRecorder(); if (flag == 0) delegate = new RecordEventToDatabase(); if (flag == 1) delegate = new RecordEventToFile(); // 设置代理 decorator.setDelegate(delegate); return decorator; } }从举的例子中可以看到,有2种业务处理逻辑,有2个具体实现,它们组成了4种事件记录方式。
Specification
在一个较为复杂的业务流程中,某些条件的满足与否决定了业务逻辑的走向,可以把这些条件抽离出来,使得任意个条件以某种关系进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,也可以预定义多个条件,使用这些条件的组合来处理查询逻辑,而不是使用逻辑判断语句来处理,那样只会让代码变得复杂。在Specification设计模式中,一个条件就是一个specification,多个specification通过串联的方式以某种逻辑关系形成一个组合式的specification。首先看一下整体的UML图:
下面是Specification接口的声明:
public interface Specification { boolean isSatisfiedBy(Object params); Specification and(Specification other); Specification or(Specification other); Specification not(); }它定义了各个条件间可用的关系:与、或、非,这三个关系所对应方法的返回值都是Specification自身,目的是为了实现 Specification之间的串联(chaining),从而形成一个关系表达式。isSatisfiedBy就是判定方法, 参数是一个Object,支持任意类型。
下面来看CompositSpecification的声明:
public abstract class CompositeSpecification implements Specification { @Override public Specification and(Specification other) { return new AndSpecification(this, other); } @Override public Specification not() { return new NotSpecification(this); } @Override public Specification or(Specification other) { return new OrSpecification(this, other); } public abstract boolean isSatisfiedBy(Object params); }它实现了Specification接口的关系判定方法,而isSatisfiedBy则仍是抽象方法,需要派生类来具体实现。下面是三个分别实现了与、或、非关系判定的派生类的声明:
public class AndSpecification extends CompositeSpecification { private final Specification b; private final Specification a; public AndSpecification(Specification a, Specification b) { this.a = a; this.b = b; } @Override public boolean isSatisfiedBy(Object params) { return a.isSatisfiedBy(params) && b.isSatisfiedBy(params); } }
public class NotSpecification extends CompositeSpecification { private final Specification a; public NotSpecification(Specification a) { this.a = a; } @Override public boolean isSatisfiedBy(Object params) { return !a.isSatisfiedBy(params); } }
public class OrSpecification extends CompositeSpecification { private final Specification b; private final Specification a; public OrSpecification(Specification a, Specification b) { this.a = a; this.b = b; } @Override public boolean isSatisfiedBy(Object params) { return a.isSatisfiedBy(params) || b.isSatisfiedBy(params); } }这些类就构成了Specification模式的核心部分,下面来看一个例子:
先定义一个男人:
public class Men { public String name; // 姓名 public boolean married; // 是否已婚 public int cars; // 拥有车的数量 public int houses; // 拥有房子的数量 public Men(String name, int cars, int houses, boolean married) { this.name = name; this.cars = cars; this.houses = houses; this.married = married; } }然后定义选男人的几个条件:
public class HasCarsSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men)params; return m.cars > 0; } }
public class HasHousesSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men) params; return m.houses > 0; } }
public class MarriedSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men) params; return m.married; } }好,下面有位女嘉宾开始选心目中的男人了:
public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Men[] candidates = { new Men("李精英", 1, 1, false), new Men("王老五", 5, 3, true), new Men("赵白领", 0, 1, false), new Men("West_Link", 0, 0, false) }; HasHousesSpecification hasHouse = new HasHousesSpecification(); HasCarsSpecification hasCar = new HasCarsSpecification(); MarriedSpecification married = new MarriedSpecification(); Specification spec = hasHouse.and(hasCar).and(married.not()); for (Men men : candidates) { if (spec.isSatisfiedBy(men)) System.out.println(men.name); } } }从Specification spec = hasHouse.and(hasCar).and(married.not()) 这行代码可以看出这位女嘉宾选择了有车并且有房的未婚男子,所以打印结果为:李精英。
Publish-Subscribe
很多项目中都有消息分发或者事件通知机制,尤其是模块化程度高的项目。例如在办公自动化系统 中,有些子系统对于新建用户这一事件很感兴趣,权限模块希望为这个新用户设置默认的权限,报表模块希望重新生成当月的报表,诸如此类的代码都写到新建用户 的业务逻辑后面,会加大耦合度,可维护性降低,并且对于每个模块都是一个独立工程的情况,这种方式更是不可取。对于简单的情形,观察者模式就适用了,如果系统中有很多地方都需要收发消息,那么它就不适用了,否则会造成类数量的膨胀,增加类的复杂性,这时候就需要一种更集中的机制,Publish-Subscribe机制是个不错的选择,它的耦合性低,各个参与者之间毫无关联。每 一个消息都有一个唯一标识,一般都用字符串来描述,比如用户管理模块中新添加了一个用户,于是它发送了一个消息:/User/Add,消息的其他信息可以放置到一个Map中。下面是一个最简单的消息订阅接口:
public interface MessageSubscriber { public void onRecived(String message, Map params); }当订阅的消息发出后,MessageSubscriber的onRecived方法就会被调 用,消息相关的特定信息存储在参数params中。 一个消息可以被多个对象订阅,一个对象可以订阅多个消息,所以onRecived的第一个参数是消息的名称,如果对象订阅了多个消息,可能需要根据消息类 型来进行具体的操作。
下面消息发送的实现类:
public class MessagePublisher { private static MessagePublisher singleton; private static Map<String, ArrayList<MessageSubscriber>> subscribers; private MessagePublisher() { } public static MessagePublisher instance() { if (singleton == null) singleton = new MessagePublisher(); return singleton; } public void register(String message, MessageSubscriber subscriber) { if (subscriber == null) return; if (subscribers == null) subscribers = new LinkedHashMap<String, ArrayList<MessageSubscriber>>(); ArrayList<MessageSubscriber> subscriberList = subscribers.get(message); if (subscriberList == null) { subscriberList = new ArrayList<MessageSubscriber>(); subscribers.put(message, subscriberList); } subscriberList.add(subscriber); } public void publish(String message, Map params) { if (subscribers == null) return; ArrayList<MessageSubscriber> subscriberList = subscribers.get(message); if (subscriberList == null || subscriberList.isEmpty()) return; for (MessageSubscriber topicSubscriber : subscriberList) topicSubscriber.onRecived(message, params); } }该类中主要包含两个方 法:register用来注册消息订阅者,publish用来发送消息。这样,对某个事件感兴趣的模块就可以通过MessagePublisher来订阅 这个相关的消息,而产生事件的模块就可以通过MessagePublisher将其发布出去。
测试示例:
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub MessagePublisher messagePublisher = MessagePublisher.instance(); messagePublisher.register("/User/Add", new ASubscriber()); messagePublisher.register("/User/Del", new BSubscriber()); Map<String, String> params = new HashMap(); params.put("id", "001"); params.put("name", "zero"); messagePublisher.publish("/User/Add", params); messagePublisher.publish("/User/Del", params); } } class ASubscriber implements MessageSubscriber { @Override public void onRecived(String message, Map params) { // TODO Auto-generated method stub System.out.println("ASubscriber : message=" + message + ", content = " + params); } } class BSubscriber implements MessageSubscriber { @Override public void onRecived(String message, Map params) { // TODO Auto-generated method stub System.out.println("BSubscriber : message=" + message + ", content = " + params); } }
ASubscriber订阅“/User/Add”的内容,BSubscriber订阅“/User/Del”的内容。当messagePublisher发布时消息时,订阅该消息的将会执行onRecived()方法。
相关文章推荐
- 领域模型、贫血模型、充血模型概念总结
- Java的整体认识--类的初步理解和第一个Java程序
- VS2013 编译程序时提示 无法查找或打开 PDB 文件
- struts2修改prepare拦截器
- VS2013 编译程序时提示 无法查找或打开 PDB 文件
- Linux电源管理【转】
- mysql替换成对括号
- WebSocket协议
- linux开启内部路由转发功能
- 高性能网络编程7--tcp连接的内存使用
- Lucene+ik的分页和多条件模糊交集搜索
- 项目经验总结
- JS调用中文乱码怎么办
- eclipse上cvs服务器端的配置
- mysql replication(主从复制)(三)GTIDs
- nyoj--44--子串和(动态规划)
- 生活中面向对象的实例
- android studio编译项目,9 patch图片报错Crunching Cruncher
- 技术博客网址
- 自定义View----Android九宫格手势密码解锁