package design_pattern.observer.delegate;
import java.lang.reflect.Method;
/**
* 使用【事件委托】来完善观察者模式
* 当一个对象的改变会影响想到其它多个对象时,就可以考虑用观察者模式
* 因为观察者中的‘抽象通知者’还是依赖‘抽象观察者,也就是说,万一没有了抽象观察者这样的接口,
* 就实现不了相关通知的功能。为了弥补观察者模式的不足,出现了事件委托模式;
*
* 委托就是一种引用方法的类型,一旦为委托分配了方法,委托将与该方法具有完全相同的行为。
* 委托方法的使用可以像其他任何方法一样,具有参数和返回值,委托可以看作是对函数的抽象,是函数的‘类’,
* 委托的实例将代表一个具体的函数。
*
* 一个委托可以搭载多个方法,所有方法被依次唤起。更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。
* 即:不同的对象可以执行不同的事件【方法】
* 因为 java 没有直接实现委托的相关类或者方法,因此可以通过反射的方式添加事件来处理委托。
*/
public class Event {
//要执行方法的对象
private Object object;
//要执行的方法名称
private String methodName;
//要执行方法的参数
private Object[] params;
//要执行方法的参数类型
private Class[] paramTypes;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getParams() {
return params;
}
public void setParams(Object[] params) {
this.params = params;
}
public Class[] getParamTypes() {
return paramTypes;
}
public void setParamTypes(Class[] paramTypes) {
this.paramTypes = paramTypes;
}
public Event(){
}
public Event(Object object,String methodName,Object...args){
this.object=object;
this.methodName=methodName;
this.params=args;
contractParamTypes(this.params);
}
//根据参数数组生成参数类型数组
private void contractParamTypes(Object[] params){
this.paramTypes=new Class[params.length];
for(int i=0;i<params.length;i++){
this.paramTypes[i]=params[i].getClass();
}
}
//执行该 对象的该方法
public void invoke() throws Exception{
Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());
if(null==method){
return;
}
method.invoke(this.getObject(), this.getParams());
}
}
package design_pattern.observer.delegate;
import java.util.ArrayList;
import java.util.List;
/**
* 定义一个事件处理器
*/
public class EventHandler {
//使用一个List
private List<Event> objects;
public EventHandler(){
objects=new ArrayList<>();
}
//添加某个对象要执行的事件,及需要的参数
public void addEvent(Object object,String methodName,Object...args){
objects.add(new Event(object,methodName,args));
}
//通知所有的对象执行指定的事件
public void notifyEvent() throws Exception{
for(Event e : objects){
e.invoke();
}
}
}
package design_pattern.observer.delegate;
/**
* 抽象通知者
*/
public abstract class Notifier {
private String subjectState;
private EventHandler eventHandler = new EventHandler();
public EventHandler getEventHandler() {
return eventHandler;
}
public void setEventHandler(EventHandler eventHandler) {
this.eventHandler = eventHandler;
}
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
//增加需要监听的类
public abstract void addObserver(Object object, String methodName, Object...args);
// 通知方法
public abstract void notifyObserver();
}
package design_pattern.observer.delegate;
/**
* 前台通知者
*/
public class SecretaryNotifier extends Notifier {
public SecretaryNotifier(){
this.setSubjectState("号外号外,胡汉三回来了!");
}
@Override
public void addObserver(Object object, String methodName, Object... args) {
System.out.println("有新的同事委托前台小姐姐");
this.getEventHandler().addEvent(object,methodName,args);
}
@Override
public void notifyObserver() {
try {
this.getEventHandler().notifyEvent();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package design_pattern.observer.delegate;
/**
* NBA观察者
*/
public class NBAObserver {
private String name;
public NBAObserver(String name){
this.name = name;
}
public void closeNBADirectSeeding(String subjectState) {
System.out.printf("%s %s 关闭NBA直播,继续工作!\n",subjectState,name);
}
}
package design_pattern.observer.delegate;
/**
* 股票观察者
*/
public class StockObserver {
private String name;
public StockObserver(String name){
this.name = name;
}
public void closeStockMarket(String subjectState) {
System.out.printf("%s %s 关闭股票行情,继续工作!\n",subjectState, name);
}
}
/**
* 测试方法
*/
public class EventTest {
public static void main(String[] args) {
//通知者
Notifier notifier = new SecretaryNotifier();
//股票观察者
StockObserver stockObserver = new StockObserver("张三");
//NBA观察者
NBAObserver nbaObserver = new NBAObserver("李四");
//注册观察者
notifier.addObserver(stockObserver,"closeStockMarket",notifier.getSubjectState());
notifier.addObserver(nbaObserver,"closeNBADirectSeeding",notifier.getSubjectState());
//通知观察者
notifier.notifyObserver();
}
}
学到了就要教人,赚到了就要给人!
The more I think, the luckier I am.
【越思考,越幸运】