设计模式

设计模式实践-观察者模式

2020-10-16  本文已影响0人  h2coder

什么是观察者模式?什么时候用?

观察者模式常用于GUI。它适用于一对多事件触发的场景,当一个对象的状态被改变,所有依赖它的对象都会得到通知并更新。

场景

怎么实现观察者模式?

经典观察者模式,一般会涉及以下几个对象:

而我们平时写的接口回调,一般是没有太多抽象接口的,只有以下几个对象:

其实经典的观察者模式,在JDK中已经提供了Observable和Observer接口,我们直接使用即可。

观察者模式实践,解耦分发聊天室消息

在开发聊天室的过程中,使用WebSocket接收后端发送过来的消息,一般为Json结构,我们就需要解析,解析完成为Java Bean后,再使用Bean进行UI更新。如果直接将解析操作直接写在Activity肯定是很臃肿的(消息种类非常多,将近10种),势必需要抽象去别的类上。而聊天室是分免费和付费的,有一部分消息是他们公用的(一般抽取一个基类),而有一些是个别类型的聊天室才需要使用,那么为了将消息结果解析方消息结果使用方解耦开来,我们可以使用观察者模式。

实现步骤

  1. Parser,消息解析方,解析消息Json,并提供消息回调,内部存储回调对象的引用。
  2. OnReceiveMsgCallback,消息结果使用方,为一个接口,每个监听对象都需要实现。
  3. 具体的OnReceiveMsgCallback实现类,聊天室有2种类型,再加上公用消息基类监听,一共3个。

最后,OnReceiveMsgCallback接口,提供空实现的实现类,每种类型的聊天室,看业务需要复写具体需要处理的类型回调方法即可。

别废话,上代码~

  1. 消息注册,3个示例一下(其他类型都是一样套路),接收房间信息、限制发送消息、订单支付消息。一般后端给的Json中,每种消息类型都有一个type来区分消息类型,我们每个消息解析判断本地Json中的type是否是我们这个接收器能处理的类型后再解析即可,解析完成后进行接口回调给外部即可。

    • 房间消息,不管免费、付费聊天室都需要。
    • 限制发送消息,免费的才需要,5条消息后,老师未回复,则产生限制,无法再发送,除非老师进行回复后,方可解除限制。
    • 订单支付消息,付费聊天室使用,用户下单后发送。
public class ConsultingMsgParser {
    /**
     * 注册房间信息
     */
    private void registerRoomInfo(ObservableSubscribeProxy<WebSocketInfo> proxy) {
        proxy.subscribe(new WebSocketGenericObserver<WssResponseModel<RoomInfoModel>>() {

            @Override
            protected boolean isTargetType(String json) {
                    //判断是否能够解析
                return canHandleJson(json, WssCommandTypeEnum.ROOM_INFO);
            }

            @Override
            protected ObservableSource<WssResponseModel<RoomInfoModel>> onParseData(String json) {
                    //能够解析,则解析并返回解析结果
                return parseResponse(json, new TypeToken<WssResponseModel<RoomInfoModel>>() {
                }.getType());
            }

            @Override
            protected void onMessage(WssResponseModel<RoomInfoModel> response) {
                   //通知观察者们,将结果传入
                for (OnReceiveMsgCallback callback : mOnReceiveMsgCallbackList) {
                    callback.onReceiveRoomInfo(response);
                }
            }
        });
    }
    
    /**
     * 注册免费聊天消息限制消息
     */
    private void registerFreeMsgLimit(ObservableSubscribeProxy<WebSocketInfo> proxy) {
        proxy.subscribe(new WebSocketGenericObserver<WssResponseModel<SendMsgLimitModel>>() {
            @Override
            protected boolean isTargetType(String json) {
                return canHandleJson(json, WssCommandTypeEnum.SEND_MSG_LIMIT);
            }

            @Override
            protected ObservableSource<WssResponseModel<SendMsgLimitModel>> onParseData(String json) {
                return parseResponse(json, new TypeToken<WssResponseModel<SendMsgLimitModel>>() {
                }.getType());
            }

            @Override
            protected void onMessage(WssResponseModel<SendMsgLimitModel> response) {
                for (OnReceiveMsgCallback callback : mOnReceiveMsgCallbackList) {
                    if (callback != null) {
                        if (MsgLimitEnum.LIMIT.getCode() == response.getData().getIsLimit()) {
                            //限制
                            callback.onReceiveSendMsgLimitMsg(response);
                        } else if (MsgLimitEnum.REMOVE_LIMIT.getCode() == response.getData().getIsLimit()) {
                            //解除限制
                            callback.onReceiveSendMsgRemoveLimitMsg(response);
                        }
                    }
                }
            }
        });
    }
    
    /**
     * 注册支付高级服务订单消息
     */
    private void registerPayServerOrderMsg(ObservableSubscribeProxy<WebSocketInfo> proxy) {
        proxy.subscribe(new WebSocketGenericObserver<WssResponseModel<PayServerOrderMsgModel>>() {
            @Override
            protected boolean isTargetType(String json) {
                return isTargetMsg(json, MsgTypeEnum.PAY_SERVER);
            }

            @Override
            protected ObservableSource<WssResponseModel<PayServerOrderMsgModel>> onParseData(String json) {
                return parseResponse(json, new TypeToken<WssResponseModel<PayServerOrderMsgModel>>() {
                }.getType());
            }

            @Override
            protected void onMessage(WssResponseModel<PayServerOrderMsgModel> response) {
                for (OnReceiveMsgCallback callback : mOnReceiveMsgCallbackList) {
                    callback.onReceivePayServerOrderMsg(response);
                }
            }
        });
    }
}
  1. 回调接口,一系列消息的回调
public interface OnReceiveMsgCallback {
    /**
     * 接收到房间信息
     */
    void onReceiveRoomInfo(WssResponseModel<RoomInfoModel> response);

    /**
     * 限制发送消息
     */
    void onReceiveSendMsgLimitMsg(WssResponseModel<SendMsgLimitModel> response);

    /**
     * 解除限制,发送消息
     */
    void onReceiveSendMsgRemoveLimitMsg(WssResponseModel<SendMsgLimitModel> response);

    /**
     * 高级服务支付订单消息
     */
    void onReceivePayServerOrderMsg(WssResponseModel<PayServerOrderMsgModel> response);
}

//因为有些消息,某种类型的聊天室不需要使用,所以提供接口空实现,具体类型聊天室看业务需要,复写对应类型的回调方法进行处理即可。
public class SimpleOnReceiveMsgCallback implements OnReceiveMsgCallback {
    @Override
    public void onReceiveRoomInfo(WssResponseModel<RoomInfoModel> response) {
    }
    
    @Override
    public void onReceiveSendMsgLimitMsg(WssResponseModel<SendMsgLimitModel> response) {
    }

    @Override
    public void onReceiveSendMsgRemoveLimitMsg(WssResponseModel<SendMsgLimitModel> response) {
    }
    
    @Override
    public void onReceivePayServerOrderMsg(WssResponseModel<PayServerOrderMsgModel> response) {
    }
}
  1. 提供注册接口回调的方法
private ArrayList<OnReceiveMsgCallback> mOnReceiveMsgCallbackList;

/**
 * 注册消息接收的回调
 */
public void registerOnReceiveMsgCallback(OnReceiveMsgCallback onReceiveMsgCallback) {
    if (mOnReceiveMsgCallbackList == null) {
        mOnReceiveMsgCallbackList = new ArrayList<>();
    }
    mOnReceiveMsgCallbackList.add(onReceiveMsgCallback);
}
  1. 3个结果处理方进行注册。

    • 房间消息,在基类注册进行处理。
    ConsultingMsgParser msgParser = new ConsultingMsgParser();
    msgParser.registerOnReceiveMsgCallback(new SimpleOnReceiveMsgCallback() {
                @Override
                public void onReceiveRoomInfo(WssResponseModel<RoomInfoModel> response) {
                    //收到房间信息,将信息设置到UI...
                    //开始获取消息列表...
                    getMsgList();
                }
    }
    
    • 限制发送消息,免费聊天室进行注册。
    msgParser.registerOnReceiveMsgCallback(new SimpleOnReceiveMsgCallback() {
    @Override
            public void onReceiveSendMsgLimitMsg(WssResponseModel<SendMsgLimitModel> response) {
                super.onReceiveSendMsgLimitMsg(response);
                //设置为限制发送消息状态
                mBanTipContext.setState(new LimitSendMsgBanTipState(model));
            }
    
            @Override
            public void onReceiveSendMsgRemoveLimitMsg(WssResponseModel<SendMsgLimitModel> response) {
                super.onReceiveSendMsgRemoveLimitMsg(response);
                //解除限制发送消息,恢复到普通状态
                mBanTipContext.setState(new NormalBanTipState());
            }
    }
    
    • 用户下单消息,付费聊天室进行注册
        msgParser.registerOnReceiveMsgCallback(new SimpleOnReceiveMsgCallback() {
        @Override
            public void onReceivePayServerOrderMsg(WssResponseModel<PayServerOrderMsgModel> response) {
                   //接收下单成功的系统消息
                //插入时间戳条目
                insertTimestampItem(response.getDateTime());
                //插入系统提示条目
                addSystemMsg(new PayServerSuccessTipModel());
                //滚动到底部
                scrollToBottom();
            }
        }
    

总结

上一篇 下一篇

猜你喜欢

热点阅读