14.观察者模式

package observerModel;

import java.util.ArrayList;
import java.util.List;


/**
 * 这里是一个 上课睡觉 让别人放风的例子
 * 
 * 这里放风的人 和睡觉的人相互耦合了 就是放风类中有睡觉的人 睡觉类中有放风的人 
 * 
 */
public class Commonly {
	public static void main(String[] args) {
		 Fangfeng fangfeng = new Fangfeng();
		 
		 Sleep sleep = new Sleep(fangfeng, "打不死的小强");
		 Sleep sleep2 = new Sleep(fangfeng, "滚出去的小明");
		 
		 //放风的人负责通知这俩人
		 fangfeng.Add(sleep);
		 fangfeng.Add(sleep2);
		 //老师来了 放风的人状态改变
		 fangfeng.setAction("班主任来了!");
		 //通知别人
		 fangfeng.Notify();
		 
	}
}

/*
 * 放风的人 
 */
class Fangfeng{
	//睡觉人列表
	private List<Sleep> sleeps = new ArrayList<Sleep>();
	
	public String Action;
	
	//增加
	public void Add(Sleep sleep){
		sleeps.add(sleep);
	}
	
	//通知老师来了
	public void Notify(){
		for (Sleep sleep : sleeps) {
			sleep.Update();
		}
	}

	public String getAction() {
		return Action;
	}

	public void setAction(String action) {
		Action = action;
	}
	
	
}

/*
 * 睡觉的人
 */
class Sleep{
	//名字
	private String name;
	//放风者
	private Fangfeng fangfeng;
	public Sleep(Fangfeng fangfeng,String name) {
		this.fangfeng = fangfeng;
		this.name = name;
	}
	public void Update(){
		System.out.println(fangfeng.getAction()+":"+name+" 起来学习!");
	}
}


package observerModel;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式:
 * 百度百科解释:
 * 有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式,是软件设计模式的一种
 * 在此种模式中,一个目标物件管理所有相依于它的观察者物件,
 * 并且在它本身的状态改变时主动发出通知。
 * 这通常透过呼叫各观察者所提供的方法来实现。
 * 此种模式通常被用来实现事件处理系统。
 * 
 * 观察者模式(Observer)完美的将观察者和被观察的对象分离开。
 * 举个例子,用户界面可以作为一个观察者,业务数据是被观察者,
 * 用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。
 * 面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。
 * 一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
 * 
 * 
 * 
 * 
 *@author LiMing  E-mail:1151143484@qq.com
 *@date 2017年6月18日  上午9:38:31
 */
public class ObserverModel {
	public static void main(String[] args) {
		
		Teacher teacher = new Teacher();
		//需要被通知的人
		Sleeps sleeps = new Sleeps("滚出去的小明", teacher);
		GoSteady goSteady = new GoSteady("打不死的小强", teacher);
		//把需要通知的人加进来
		teacher.Add(sleeps);
		teacher.Add(goSteady);
		
		
		//设置老师状态
		teacher.setAction("老师我来了!");
		//通知所有人
		teacher.Notify();
		
		//这里再强调一下 这里的只是举个例子 老师状态改变之后会通知学生 可能不合理 但是就是这么个意思  
		//老师就相当于是主题   坏学生就是订阅者 他们不用主动去看老师来不来 等老师来了会告诉他们 这样他们就可以专注自己的事儿(睡觉,搞对象)
		//在代码中 就是每个类去实现自己的功能 不用理会别的功能 如果有需要别的类会通知他
		
		
		/*
		 * 为啥使用观察者?
		 * 将一个系统分割成一系列相互协作的类有一个不好的副作用 那就是需要维护相关对象之间的一致性 我们不希望为了维持一致性而使各类紧密耦合 ,
		 * 这样会给维护、扩展和重用都带来不便
		 * 
		 * 而观察者模式的关键对象是主题Subject(老师)    和观察者 Observer(学生) ,一个Subject可以有任意数目的依赖他的observer
		 * 一旦subject的状态发生了改变  所有的observer都可以得到通知
		 * 而任何一个具体的观察者 不知道 也不需要知道其他观察者的存在(睡觉的人 不需要知道搞对象的存在)
		 * 
		 * 
		 */
		
		
		
		/*
		 * 观察者模式的不足:
		 * 第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
		 * 第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
		 * 第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
		 * 第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
		 *
		 * 第五、 如果观察者没有抽象类  也就是没有Observer 类(一些功能可能不是自己编写的 可能用的是开源的或者其他的人东西)只有Sleeps 
		 * 但是Sleeps没有继承Observer 所以Teacher类 没有办法使用抽象的Observer 这个时候可以使用事件委托
		 *
		 */
		
		/*
		 * 用事件委托实现
		 */
		Teachers teachers = new Teachers();
		SleepStu sleepStu =new  SleepStu("滚出去的小明",teachers);
		GoSteadyStu goSteadyStu = new GoSteadyStu("打不死的小强", teachers);
		
		
		//绑定委托事件
		teachers.getUpdate().add(new Event(sleepStu, "UpdateSleepStu", null));
		teachers.getUpdate().add(new Event(goSteadyStu, "UpdateGoSteadyStu", null));
		
		//设置老师状态
		teachers.setAction("老师来了!!");
		
		//通知
		teachers.Notify();
		
		
		
		
	}
}

/*
 * 抽象放风类
 */
interface Subject{
	void Add(Observer observer);
	void Delete(Observer observer);
	void Notify();
	public String getAction() ;
	public void setAction(String action) ;
} 

/*
 * 抽象睡觉类
 */
abstract class Observer{
	public String name;
	public Subject sub;
	public Observer(){
		
	}
	public Observer(String name,Subject sub){
		this.name = name;
		this.sub = sub;
	}
	public abstract void Update();
}



/**
 * 具体的放风的人
 * 不要误会 这里的意思不是说老师来放风 
 * 而是什么意思呢? 这里的意思是 放风的人观察的对象是老师 老师状态改变了 放风的人就要通知睡觉的(或者干其他偷偷摸摸的事儿)人 
 */
class Teacher implements Subject{
    private List<Observer> list = new ArrayList<Observer>();
    private String Action;
	public void Add(Observer observer) {
		list.add(observer);
	}
	public void Delete(Observer observer) {
		list.remove(observer);
	}
	public void Notify() {
		for (Observer observer : list) {
			observer.Update();
		}
	}
	public String getAction() {
		return Action;
	}
	public void setAction(String action) {
		Action = action;
	}
	
	
}



/*
 * 睡觉的人
 */
class Sleeps extends Observer{
    public Sleeps(String name,Subject sub){
    	super(name, sub);
    }
	public void Update() {
		System.out.println(sub.getAction() +":"+name +"停止睡觉!!" );
	}
	
}
/*
 * 搞对象的人
 */
class GoSteady extends Observer{
    public GoSteady(String name,Subject sub){
    	super(name, sub);
    }
	public void Update() {
		System.out.println(sub.getAction() +":"+name +"停止搞对象!!" );
	}
	
}


/**
 * 事件委托
 */
 
class Event{
	  //要执行方法的对象   
    private Object object;   
    //要执行的方法名称   
    private String methodName;   
    //要执行方法的参数   
    private Object[] params;   
    //要执行方法的参数类型   
    private Class[] 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){  
    	if(params == null ) return ;
        this.paramTypes=new Class[params.length];   
        for(int i=0;i<params.length;i++){   
        						//获取参数类型
            this.paramTypes[i]=params[i].getClass();   
        }   
    }   
       
    public Object getObject() {   
        return object;   
    }   
       
    /*
     * 执行该对象的该方法   
     */
    public void invoke() throws Exception{
        Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());   
        if(null==method){   
            return;   
        }   
       
        method.invoke(this.getObject(), this.getParams());   
    }
    
    
    /*
     * get  set  方法
     */
	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 void setObject(Object object) {
		this.object = object;
	}  
}

/*
 * 睡觉的同学
 */
class SleepStu{
	private String name;
	private Subject2 sub;
	 public SleepStu(String name,Subject2 sub){
	    	 this.name = name;
	    	 this.sub = sub;
	    }
		public void UpdateSleepStu() {
			System.out.println(sub.getAction() +":"+name +"停止睡觉!!" );
		} 
}
/*
 * 搞对象的同学
 */
class GoSteadyStu{
	private String name;
	private Subject2 sub;
	 public GoSteadyStu(String name,Subject2 sub){
	    	 this.name = name;
	    	 this.sub = sub;
	    }
	//可以看见 这里的方法 跟类SleepStu中的方法名不一样了(这中情况是存在的 如果这两个类 由不同的开发商提供 那么会存在这种情况)
	public void UpdateGoSteadyStu() {
		System.out.println(sub.getAction() +":"+name +"停止搞对象!!" );
	} 
}

interface Subject2{
	void Notify();
	public String getAction() ;
	public void setAction(String action) ;
}
/*
 * 这里不再添加和删除Observer(因为没有抽象的Observer 没有办法统一添加)
 */
class Teachers implements Subject2 {
	private String Action;
	
	public void Notify() {
		//执行委托的事件
		try {
			for (Event event : Update) {
				event.invoke();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//委托多个事件
	public List<Event> Update = new ArrayList<>();
	
	public List<Event> getUpdate() {
		return Update;
	}
	public void setUpdate(List<Event> update) {
		Update = update;
	}
	public String getAction() {
		return Action;
	}
	public void setAction(String action) {
		this.Action = action;
	}
	
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值