观察者模式

几个概念

  1. Subject 抽象主题角色(你自己):也就是抽象的被观察者对象,里面保存了所有的观察者对象引用列表,提供了注册和反注册的功能。
  2.   ConcreteSubject具体的主题角色(你的举动):将有关状态存入各ConcreteObserver对象    当它的状态发送改变时,向它的各个观察者发出通知 。
  3.   Observer 抽象观察者(女朋友基类) :为所有的具体观察者定义一个接口,在得到通知时更新自己。
  4.   ConcreteObserver 具体观察者(具体女朋友):维护一个指向ConcreteObserver对象的引用 ,存储有关状态,这些状态应与目标的状态保持一致,实现Observer的更新接口是自身状态与目标的状态保持一致

具体方案实现:
(1)EventSubjectInterface:抽象的主题角色实现
/**
 * 抽象的主题角色
 * @author zhiwu_yan
 * @since 2015年04月06日
 * @version 1.0
 */
public interface EventSubjectInterface {
    /**
     * 注册观察者
     * @param observer
     */
    public void registerObserver(EventObserver observer);

    /**
     * 反注册观察者
     * @param observer
     */
    public void removeObserver(EventObserver observer);

    /**
     * 通知注册的观察者进行数据或者UI的更新
     */
    public void notifyObserver(String eventType);
}
(2)EventSubject:具体的主题角色的实现
/**
 * 具体的主题角色的实现,这里用来监听事件的发生,采用单例模式来实现
 * @author zhiwu_yan
 * @since 2015年04月06日
 * @version 1.0
 */
public class EventSubject implements EventSubjectInterface{

    private List<EventObserver> mEventObservers=new ArrayList<EventObserver>();
    private static volatile EventSubject mEventSubject;
    private EventSubject(){

    }

    public synchronized static EventSubject getInstance(){
        if(mEventSubject ==null){
            mEventSubject =new EventSubject();
        }
        return mEventSubject;
    }

    @Override
    public void registerObserver(EventObserver observer) {
        synchronized (mEventObservers){
            if(observer!=null){
                if(mEventObservers.contains(observer)){
                    return;
                }
                mEventObservers.add(observer);
            }
        }

    }

    @Override
    public void removeObserver(EventObserver observer) {
        synchronized (mEventObservers){
            int index = mEventObservers.indexOf(observer);
            if (index >= 0) {
                mEventObservers.remove(observer);
            }
        }
    }

    @Override
    public void notifyObserver(String eventType) {
        if(mEventObservers!=null && mEventObservers.size()>0 && eventType!=null){
            for(EventObserver observer:mEventObservers){
                observer.dispatchChange(eventType);
            }
        }

    }
}
(3)EventObserverInterface:抽象观察者对象
/**
 * 观察者接口
 * @author zhiwu_yan
 * @since 2015年04月06日
 * @version 1.0
 */
public interface EventObserverInterface {
    /**
     * 根据事件进行数据或者UI的更新
     * @param eventType
     */
    public void dispatchChange(String eventType);
}
(4)EventObserver:具体的抽线观察者
/**
 * 用于更新UI,这里执行更新UI的onChange方法
 * @author  zhiwu_yan
 * @since   2015年04月06
 * @version 1.0
 */
public abstract class EventObserver implements EventObserverInterface {

    private Handler mHandler;

    public EventObserver(){
        mHandler=new Handler(Looper.getMainLooper());
    }


    public abstract void onChange(String eventType);

    @Override
    public void dispatchChange(String eventType){
        mHandler.post(new NotificationRunnable(eventType));
    }

    private final class NotificationRunnable implements Runnable{
        private String mEventType;
        public NotificationRunnable(String eventType){
            this.mEventType=eventType;
        }
        @Override
        public void run() {
            EventObserver.this.onChange(mEventType);
        }
    }
}
(5)前面已经说过了,Android里面我们需要定义一个带观察者模式的BaseActivity用来给某些需要监听的业务的Activity使用,这样只要继承了该Activity的都是一个具体的观察者对象。
/**
 * 带有观察者模式的Activity,本质上就是观察者
 * @author  zhiwu_yan
 * @since  2015年04月6日 20:41
 * @version 1.0
 */
public abstract class BaseObserverActivity extends ActionBarActivity {

    private ActivityEventObserver mActivityEventObserver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivityEventObserver=new ActivityEventObserver(this);
        registerObserver(mActivityEventObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        removeObserver(mActivityEventObserver);
    }


    public void registerObserver(EventObserver observer) {
        final String[] observerEventTypes=getObserverEventType();//获取所有需要监听的业务类型
        if(observerEventTypes!=null && observerEventTypes.length>0){
            final EventSubject eventSubject=EventSubject.getInstance();
            eventSubject.registerObserver(observer);

        }

    }

    public void removeObserver(EventObserver observer) {
        final String[] observerEventTypes=getObserverEventType();//获取所有需要监听的业务类型
        if(observerEventTypes!=null && observerEventTypes.length>0){
            final EventSubject eventSubject=EventSubject.getInstance();
            eventSubject.removeObserver(observer);
        }
    }

    /**
     * 该方法会在具体的观察者对象中调用,可以根据事件的类型来更新对应的UI,这个方法在UI线程中被调用,
     * 所以在该方法中不能进行耗时操作,可以另外开线程
     * @param eventType 事件类型
     */
    protected abstract void onChange(String eventType);

    /**
     * 通过这个方法来告诉具体的观察者需要监听的业务类型
     * @return
     */
    protected abstract String[] getObserverEventType();

    private static class ActivityEventObserver extends EventObserver {
        //添加弱引用,防止对象不能被回收
        private final WeakReference<BaseObserverActivity> mActivity;
        public ActivityEventObserver(BaseObserverActivity activity){
            super();
            mActivity=new WeakReference<BaseObserverActivity>(activity);
        }

        @Override
        public void onChange(String eventType) {
            BaseObserverActivity activity=mActivity.get();
            if(activity!=null){
                activity.onChange(eventType);
            }
        }
    }


}
另外我们需要定义一个可以动态扩展的事件类型:EventType
/**
 * 所有的业务类型,在这里写,方便管理
 * @author zhiwu_yan
 * @since 2015年04月06日
 * @version 1.0
 */
public class EventType {

    private static volatile EventType mEventType;
    private final static Set<String> eventsTypes = new HashSet<String>();

    public final static String UPDATE_MAIN="com.updateMain";
    public final static String UPDATE_Text="com.updateText";
    private EventType(){
        eventsTypes.add(UPDATE_MAIN);
        eventsTypes.add(UPDATE_Text);
    }

    public static EventType getInstance(){
       if(mEventType==null){
           mEventType=new EventType();
       }
        return mEventType;
    }

    public boolean contains(String eventType){
        return eventsTypes.contains(eventType);
    }

}
我这里主要定义个2个事件类型,如果需要你可以定义N个事件类型,只要把你需要定义的事件添加到事件类表里面去就可以了。
我们在通知某个页面需要更新的时候只需呀调用如下方法:
EventSubject eventSubject=EventSubject.getInstance();
        EventType eventTypes=EventType.getInstance();
        if(eventTypes.contains(eventType)){
            eventSubject.notifyObserver(eventType);
        }
为了便于管理我们也新建一个工具类:
/**
 * 通知中心,用来通知更新数据或者UI,采用单例模式
 * @author zhiwu_yan
 * @since 2015年04月6日
 * @version 1.0
 */
public class Notify {

    private static volatile Notify mNotify;
    private Notify(){

    }

    public static Notify getInstance(){
        if(mNotify==null){
            mNotify=new Notify();
        }
        return mNotify;
    }

    public void NotifyActivity(String eventType){
        EventSubject eventSubject=EventSubject.getInstance();
        EventType eventTypes=EventType.getInstance();
        if(eventTypes.contains(eventType)){
            eventSubject.notifyObserver(eventType);
        }
    }
}
到这里基本的框架就完成,我们看看怎么使用。
使用方法
定义一个A页面:MainActivity。这个页面是一个观察者,需要监听来自其他页面的一些通知,一旦有修改就根据对应的的事件来做出不同的处理:
public class MainActivity extends BaseObserverActivity {

    private TextView mLableTv;
    private ImageView mPicIv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLableTv=(TextView) findViewById(R.id.label_tv);
        mPicIv=(ImageView) findViewById(R.id.pic_iv);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id){
            case R.id.go_other_activity:
                goActivity(OtherActivity.class);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void goActivity(Class<?> activity){
        Intent intent=new Intent(this,activity);
        startActivity(intent);
    }

    @Override
    protected void onChange(String eventType) {
        if(EventType.UPDATE_MAIN==eventType){
            mPicIv.setImageResource(R.mipmap.pic_two);
        }else if(EventType.UPDATE_Text==eventType){
            mLableTv.setText("图片被更新");
        }
    }

    @Override
    protected String[] getObserverEventType() {
        return new String[]{
                EventType.UPDATE_MAIN,
                EventType.UPDATE_Text
        };
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        startActivityForResult();
    }
}
主要看一下:onChange 方法:根据事件类型来更新不同的图片,而在getObserverEventType()中我们定义了该观察者需要观察的业务类型,其它业务类型则会被忽略。
我们的B页面:也就是发出通知的页面,APP上面的设置页面,唯一的作用就是通知观察者:
public class OtherActivity extends ActionBarActivity {
    private Button mUpdateBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.other_activity);
        mUpdateBtn=(Button) findViewById(R.id.update_edit_btn);
        mUpdateBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Notify.getInstance().NotifyActivity(EventType.UPDATE_Text);
                Notify.getInstance().NotifyActivity(EventType.UPDATE_MAIN);
            }
        });
    }


}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值