混合模式:观察者模式+中介者模式

有一个产品它有多个触发事件,它产生的时候触发一个创建事件,修改的时候触发修改事件,删除的时候触发删除事件,这就类似于我们的文本框,初始化(也就是创建)的时候要触发一个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

如果想继续扩展:

  • 使用责任链模式,可以解决一个处理者处理多个事件的问题;
  • 使用模板方法模式,可以实现处理者的启用、停用等;
  • 使用装饰模式,可以实现事件的包装、处理者功能的强化等。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥羊汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值