观察者模式

定义

简单说,对象间定义了一对多的依赖,当一个对象的改变,可以通知依赖的对象。

java 支持

观察者实现接口

public interface Observer{
    
    void update(Observable 0, Object arg);
}

主题 (被观察者类)

public class Observable{
    
    private boolean changed = false;
    
    //一个持有观察者的容器
    private Vector<Observer> obs;
    
    public Observable(){
        obs = new Vector<>();
    }
    
    //添加
    
    public synchronized void addObserver(Observer o){
        
        if(0 == null){
            throw new NullPointerException
        }
        if(!obs.contains(o)){
            obs.addElements(o)
        }
    }
    
    // 移除
     public synchronized void deleteObserver(Observer o){
         obs.removeElement(o);
     }
     
     public synchronized void deleteObservers(){
         obs.removeAllElements();
     }
    
    
    //通知方法
    public void notifyObservers(){
        notifyObservers(null);
    }
    
    
    public void notifyObservers(Object arg){
        
        Object[] arrLocal;
        
        synchronized(this){
            if(!hasChanged){
                return;
            }
            
            arrlocal = obs.toArray();
            clearChanged();
            
        }
        
        for(int i= arrLocal.length-1; i>=0, i--){
            ((Observer)arrLocal[i]).update(this,arg);
        }
    }
    
    
    protected synchronized void setChanged(){
        changed = true;
    }
    
    public synchronized boolean hasChanged(){
        return chanaged;
    }
    
    public synchronized int countObservers(){
        return obs.size();
    }
    
    
}

观察者白话描述

被观察者 有个容器用来装观察者,需要暴露增加观察者和删除观察者的方法,之后被观察者需要知道怎么通知到观察者,也就是需要知道调用观察者的方法。

JDK通过接口,约定了通知的方法,观察都需要实现该方法。如果去掉这个Observer这个接口,同样能实现的。

变形的观察者

public class ReflectInvokeObservable {
	/**
	 * java 泛型
	 * 泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型。
	 * Class<?> c表示这个Class可以放任意的类,?表示object(所有类都隐性从Object继承的)
	 * Class<T>的作用就是指明泛型的具体类型,而Class<T>类型的变量c,可以用来创建泛型类的对象。
	 */
	
	private Class<?> [] mParameterType = null;
	
	private class ObservableStruct<T>{
		//mMethod.invoke()相当于调用Observable 的 update方法
		public Method mMethod = null;
		//相当于Observable
		public Class<?> mClass = null;
		public T mObjectRef = null;
		public ObservableStruct(T object , Method method){
			this.mMethod = method;
			this.mObjectRef = object;
			this.mClass = object.getClass();
		}
		
	}

	//相当于Observable中的 Vector<Observer> obs;
	private LinkedList<ObservableStruct<?>> mInvokeObservers = new LinkedList<>();
	
	public ObservableStruct(Class<?>[] parameterType){
		this.mParameterType = parameterType;
		
	}
	
	public <T> boolean addObserver(T t, String methodName){

		if(isAdd(t)){
			return true;
		}
		try {
			Method m = t.getClass().getMethod(methodName, mParameterType);
			ObservableStruct<?>  reflectStruct = new ObservableStruct<>(t, m);
			synchronized (this) {
				mInvokeObservers.add(reflectStruct);
			}

		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public void deleteObserver(Object object){
		synchronized (this) {
			for (ObservableStruct<?> struct : mInvokeObservers) {
				if (struct != null && struct.mObjectRef == object) {
					mInvokeObservers.remove(struct);
					return;
				}
			}
		}
	}
	
	public boolean isAdd(Object object){
		synchronized (this) {
			for (ObservableStruct<?> mInvokeObserver : mInvokeObservers) {
				if (mInvokeObserver.mObjectRef == object) {
					return true;
				}
			}
			return false;
		}
	}
	
	public void clear(){
		synchronized (this) {
			mInvokeObservers.clear();
		}
	}
	
	public void invoke(Object... params){
		
		if(arrayContentIsEqual(mParameterType, params, false)){
			checkParamsErrors(params);
		}
		try {
			callObservers(params);
		} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	public void invokeWithAcceptSuberClass(Object... params){
		if(arrayContentIsEqual(mParameterType, params, true)){
			checkParamsErrors(params);
		}
		
		try {
			callObservers(params);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	private void checkParamsErrors(Object... params){
		
		StringBuilder builder = new StringBuilder("参数类型不匹配, 期望的是:(");
		for(int i=0;i<mParameterType.length;++i)
		{
			builder.append(mParameterType[i].getName()).append(",");
		}
		builder.append("), 实际上传的是:(");
		for(int i=0;i<params.length;++i)
		{
			builder.append(params[i].getClass().getName()).append(",");
		}
		builder.append(")");
		throw new IllegalArgumentException(builder.toString());
	}
	
	private void callObservers(Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{
		LinkedList<ObservableStruct<?>> tempList = null;
		synchronized (this) {
			tempList = new LinkedList<>(mInvokeObservers);
		}
		for(ObservableStruct<?> reflectStruct : tempList){
			reflectStruct.mMethod.invoke(reflectStruct.mObjectRef, params);
		}
		tempList.clear();
		tempList = null;
	}
	
	public boolean  arrayContentIsEqual(Class<?>[] a1 , Object[] a2 , boolean isAcceptSuperClass){
		
		if(a1 == null){
			return a2 == null  || a2.length == 0;
		}
		
		if(a2 == null){
			return a1.length == 0;
		}
		
		if(a1.length != a2.length ){
			return false;
		}
		
		for(int i=0; i < a1.length ; i++ ){
			if(isAcceptSuperClass){
				if(a2[i] != null && ! a1[i].isInstance(a2[i])){
					return false;
				}
			}else{
				if(a2[i] != null && a1[i] != a2.getClass()){
					return false;
				}
			}
		}
		
		return true;
	}
}

kotlin实现

kotlin写法和java类似, 但是kotlin提供的可观察属性 Delegates.observable 标注委托支持

Design-Patterns-In-Kotlin

Examp

interface TextChangedListener {

    fun onTextChanged(oldText: String, newText: String)
}

class PrintingTextChangedListener : TextChangedListener {
    
    private var text = ""
    
    override fun onTextChanged(oldText: String, newText: String) {
        text = "Text is changed: $oldText -> $newText"
    }
}

class TextView {

    val listeners = mutableListOf<TextChangedListener>()

    var text: String by Delegates.observable("<empty>") { _, old, new ->
        listeners.forEach { it.onTextChanged(old, new) }
    }
}

Usage

val textView = TextView().apply {
    listener = PrintingTextChangedListener()
}

with(textView) {
    text = "Lorem ipsum"
    text = "dolor sit amet"
}

output

Text is changed <empty> -> Lorem ipsum
Text is changed Lorem ipsum -> dolor sit amet
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值