您的位置:首页 > 其它

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

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()方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: