有一个产品它有多个触发事件,它产生的时候触发一个创建事件,修改的时候触发修改事件,删除的时候触发删除事件,这就类似于我们的文本框,初始化(也就是创建)的时候要触发一个onLoad或onCreate事件,修改的时候触发onChange事件,双击(类似于删除)的时候又触发onDbClick事件。
主要的设计模式:
- 工厂方法模式:负责产生产品对象,方便产品的修改和扩展,并且实现产品和工厂的紧耦合,避免产品随意被创建而无触发事件的情况发生。
- 桥梁模式:在产品和事件两个对象的关系中使用桥梁模式,这样两者都可以自由地扩展而不会破坏原有的封装。
- 观察者模式:使用观察者模式,使事件的变化通知处理者,而且观察者模式可以有多个观察者,也就是说这个架构是可以有多层级、多分类的处理者。想重新扩展一个新类型(新接口)的观察者,只需要扩展ProductEvent即可。
- 中介者模式:使用中介者模式处理事件与事件和处理者与处理者之间的耦合关系。
(1)构建产品和产品工厂
- 产品要有创建、修改、销毁的动作,使用工厂方法模式。
- 产品也可以通过克隆方式产生,使用原型模式。
- 产品只能由工厂类创建,不能被其他对象通过new方式创建,用单来源调用(Single Call)方法,即一个对象只能由固定的对象初始化。
public class Product implements Cloneable {
private String name; //产品名称
private boolean canChanged = false; //属性是否可以变更
public Product(ProductManager manager,String name) {
if (manager.isCreateProduct()) {
canChanged = true;
this.name = name;
}
}
public String getName() {
return name;
}
public void setName(String name) {
if (canChanged) {
this.name = name;
}
}
@Override
public Product clone() {
Product product = null;
try {
product = (Product)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return product;
}
}
import com.sfq.impl.ProductEventType;
public class ProductManager {
private boolean isPermittedCreate = false;
//建立一个产品
public Product createProduct(String name) {
isPermittedCreate = true;
Product product = new Product(this, name);
return product;
}
//废弃一个产品
public void abandonProduct(Product p) {
p = null; //销毁掉一个产品,例如删除数据库记录
}
//修改一个产品
public void editProduct(Product p,String name) {
p.setName(name);
}
//获得是否可以创建一个产品
public boolean isCreateProduct() {
return isPermittedCreate;
}
//克隆一个产品
public Product clone(Product p) {
return p.clone();
}
}
单来源调用(Single Call):在工厂类ProductManager中定义了一个私有变量isCreateProduct,该变量只有在工厂类的createProduct函数中才能设置为true,在创建产品的时候,产品类Product的构造函数要求传递工厂对象,然后判断是否能够创建产品。
注意:采用单来源调用的两个对象一般是组合关系,两者有相同的生命期,它通常适用于有单例模式和工厂方法模式的场景中。
(2)触发事件
- 产品新建要触发事件,还要有人去处理这个事件,使用观察者模式。
- 观察者为EventDispatch类,它使用了单例模式,避免对象膨胀,但同时也带来了性能及线程安全隐患。
//定义了4个事件类型,分别是新建、修改、删除以及克隆
public enum ProductEventType {
NEW_PRODUCT(1),
DEL_PRODUCT(2),
EDIT_PRODUCT(3),
CLONE_PRODUCT(4);
private int value = 0;
private ProductEventType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
import java.util.Observable;
import com.sfq.impl.ProductEventType;
public class ProductEvent extends Observable {
private Product source; //事件起源
private ProductEventType type; //事件类型
//传入事件的源头,默认为新建类型
public ProductEvent(Product source) {
this(source,ProductEventType.NEW_PRODUCT);
}
//事件源头及事件类型
public ProductEvent(Product source, ProductEventType type) {
this.source = source;
this.type = type;
notifyEventDispatch();
}
//获得事件起源
public Product getSource() {
return source;
}
//获得事件类型
public ProductEventType getEventType() {
return this.type;
}
//通知事件处理中心
private void notifyEventDispatch() {
super.addObserver(EventDispatch.getEventDispatch());
super.setChanged();
super.notifyObservers(source);
}
}
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import com.sfq.impl.EventCustomType;
import com.sfq.impl.EventCustomer;
public class EventDispatch implements Observer {
//单例模式
private final static EventDispatch dispatch = new EventDispatch();
private EventDispatch() { //设置为私有,不允许生成新的实例
}
//获得单例对象
public static EventDispatch getEventDispatch() {
return dispatch;
}
//事件触发
@Override
public void update(Observable o, Object arg) {
}
}
被观察者ProductEvent的动作发生变化后,会通过notifyEventDispatch()方法通知观察者EventDispatch,然后观察者通过 update()方法作出反应,这里暂时空着,还没反应。
(3)关联产品和产品事件
产品和产品事件是两个独立的对象,两者都可以独立地扩展,使用桥梁模式。这里使用产品管理类ProductManagger作为桥梁。
ProductManagger类补充如下:
import com.sfq.impl.ProductEventType;
public class ProductManager {
private boolean isPermittedCreate = false;
//建立一个产品
public Product createProduct(String name) {
isPermittedCreate = true;
Product product = new Product(this, name);
//产生一个创建事件
new ProductEvent(product,ProductEventType.NEW_PRODUCT);
return product;
}
//废弃一个产品
public void abandonProduct(Product p) {
new ProductEvent(p,ProductEventType.DEL_PRODUCT);
p = null; //销毁掉一个产品,例如删除数据库记录
}
//修改一个产品
public void editProduct(Product p,String name) {
p.setName(name);
new ProductEvent(p,ProductEventType.EDIT_PRODUCT);
}
//获得是否可以创建一个产品
public boolean isCreateProduct() {
return isPermittedCreate;
}
//克隆一个产品
public Product clone(Product p) {
new ProductEvent(p,ProductEventType.CLONE_PRODUCT);
return p.clone();
}
}
(4)事件的处理
现在只有1个产品类,如果产品类很多,不可能每个产品事件都写一个处理者,对于产品事件来说,它最希望的结果就是我通知了事件处理者(也就是观察者模式的观察者),其他具体怎么处理由观察者来解决,那观察者怎么来处理这么多的事件呢?事件的处理者必然有N多个。即如下图所示:
我们可以使用中介者模式。把 EventDispatch类作为事件分发的中介者,事件的处理者都是具体的同事类,它们有着相似的行为,都是处理产品事件,但是又有不相同的逻辑,每个同事类对事件都有不同的处理行为。
package com.sfq.action;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import com.sfq.impl.EventCustomType;
import com.sfq.impl.EventCustomer;
public class EventDispatch implements Observer {
//单例模式
private final static EventDispatch dispatch = new EventDispatch();
//事件消费者
private Vector<EventCustomer> customer = new Vector<EventCustomer>();
private EventDispatch() { //设置为私有,不允许生成新的实例
}
//获得单例对象
public static EventDispatch getEventDispatch() {
return dispatch;
}
//事件触发
@Override
public void update(Observable o, Object arg) {
//事件的源头
Product product = (Product)arg;
//事件
ProductEvent event = (ProductEvent)o;
//处理者处理,这里是中介者模式的核心
for(EventCustomer e:customer) {
//处理能力是否匹配
for(EventCustomType t:e.getCustomType()) {
if (t.getValue() == event.getEventType().getValue()) {
e.exec(event);
}
}
}
}
//注册事件处理者
public void registerCustomer(EventCustomer _customer) {
this.customer.add(_customer);
}
}
import java.util.Vector;
import com.sfq.action.ProductEvent;
public abstract class EventCustomer {
//容纳每个消费者能够处理的级别
private Vector<EventCustomType> customType = new Vector<EventCustomType>();
//每个消费者都要声明自己处理哪一类别的事件
public EventCustomer(EventCustomType _type) {
addCustomType(_type);
}
//每个消费者可以消费多个事件
public void addCustomType(EventCustomType _type) {
customType.add(_type);
}
//得到自己的处理能力
public Vector<EventCustomType> getCustomType(){
return customType;
}
//每个事件都要对事件进行声明式消费
public abstract void exec(ProductEvent event);
}
public enum EventCustomType {
//新建事件
NEW(1),
//删除事件
DEL(2),
//修改事件
EDIT(3),
//克隆事件
CLONE(4);
private int value = 0;
private EventCustomType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
import com.sfq.impl.EventCustomType;
import com.sfq.impl.EventCustomer;
import com.sfq.impl.ProductEventType;
public class Beggar extends EventCustomer {
public Beggar() {
super(EventCustomType.DEL);
}
@Override
public void exec(ProductEvent event) {
//事件的源头
Product p = event.getSource();
//事件类型
ProductEventType type = event.getEventType();
System.out.println("乞丐处理事件:" + p.getName() + "销毁,事件类型=" + type);
}
}
import com.sfq.impl.EventCustomType;
import com.sfq.impl.EventCustomer;
import com.sfq.impl.ProductEventType;
public class Commoner extends EventCustomer {
public Commoner() {
super(EventCustomType.NEW);
}
@Override
public void exec(ProductEvent event) {
//事件的源头
Product p = event.getSource();
//事件类型
ProductEventType type = event.getEventType();
System.out.println("平民处理事件:" + p.getName() + "诞生记,事件类型=" + type);
}
}
import com.sfq.impl.EventCustomType;
import com.sfq.impl.EventCustomer;
import com.sfq.impl.ProductEventType;
public class Nobleman extends EventCustomer {
public Nobleman() {
super(EventCustomType.EDIT);
super.addCustomType(EventCustomType.CLONE);
}
@Override
public void exec(ProductEvent event) {
//事件的源头
Product p = event.getSource();
//事件类型
ProductEventType type = event.getEventType();
if (type.getValue() == EventCustomType.CLONE.getValue()) {
System.out.println("贵族处理事件:" + p.getName() + "克隆,事件类型=" + type);
} else {
System.out.println("贵族处理事件:" + p.getName() + "修改,事件类型=" + type);
}
}
}
import com.sfq.action.Beggar;
import com.sfq.action.Commoner;
import com.sfq.action.EventDispatch;
import com.sfq.action.Nobleman;
import com.sfq.action.Product;
import com.sfq.action.ProductManager;
public class Client {
public static void main(String[] args) {
//获得事件分发中心
EventDispatch dispatch = EventDispatch.getEventDispatch();
//接受乞丐对事件的处理
dispatch.registerCustomer(new Beggar());
//接受平民对事件的处理
dispatch.registerCustomer(new Commoner());
//接受贵族对事件的处理
dispatch.registerCustomer(new Nobleman());
//建立一个原子弹生成工厂
ProductManager factory = new ProductManager();
//制作一个产品
System.out.println("-----模拟创建产品事件-----");
System.out.println("创建一个叫做小男孩的原子弹");
Product p = factory.createProduct("小男孩原子弹");
//修改一个产品
System.out.println("\n-----模拟修改产品事件-----");
System.out.println("把小男孩原子弹修改为胖子号原子弹");
factory.editProduct(p, "胖子号原子弹");
//再克隆一个原子弹
System.out.println("\n-----模拟克隆产品事件-----");
System.out.println("克隆胖子号原子弹");
factory.clone(p);
//遗弃一个产品
System.out.println("\n-----模拟销毁产品事件-----");
System.out.println("遗弃胖子号原子弹");
factory.abandonProduct(p);
}
}
结果
-----模拟创建产品事件-----
创建一个叫做小男孩的原子弹
平民处理事件:小男孩原子弹诞生记,事件类型=NEW_PRODUCT
-----模拟修改产品事件-----
把小男孩原子弹修改为胖子号原子弹
贵族处理事件:胖子号原子弹修改,事件类型=EDIT_PRODUCT
-----模拟克隆产品事件-----
克隆胖子号原子弹
贵族处理事件:胖子号原子弹克隆,事件类型=CLONE_PRODUCT
-----模拟销毁产品事件-----
遗弃胖子号原子弹
乞丐处理事件:胖子号原子弹销毁,事件类型=DEL_PRODUCT
如果想继续扩展:
- 使用责任链模式,可以解决一个处理者处理多个事件的问题;
- 使用模板方法模式,可以实现处理者的启用、停用等;
- 使用装饰模式,可以实现事件的包装、处理者功能的强化等。