哪些常见的场景适合使用
策略模式
呢?我在写聊天界面的时候遇到了一个非常适合用策略模式
的地方,与大家分享 (本文以Android的聊天界面为案例,ios也是一个道理)
本文不做介绍策略模式
到底是什么,网上别人写的很详细。
聊天界面的ViewHolder (ios中叫Cell)一共有哪几种类型?
ViewHolder | 位置 | 内容 | 上传状态View |
---|---|---|---|
MySend_Text_ViewHolder | 左 | 发文字 | 有 |
MyReceived_Text_ViewHolder | 右 | 收文字 | 没有 |
MySend_Image_ViewHolder | 左 | 发图片 | 有 |
MyReceived_Image_ViewHolder | 右 | 收图片 | 没有 |
MySend_Voice_ViewHolder | 左 | 发语音条 | 有 |
MyReceived_Voice_ViewHolder | 右 | 收语音条 | 没有 |
MySend_Location_ViewHolder | 左 | 发位置 | 有 |
MyReceived_Location_ViewHolder | 右 | 收位置 | 没有 |
MySend_Call_ViewHolder | 左 | 发语音通话 | 有 |
MyReceived_Call_ViewHolder | 右 | 收语音通话 | 没有 |
老方案1:左边是BaseTextHolder,右边的MySend_Text_ViewHolder extend BaseTextHolder,然后加上progressbar 和 statusIV
缺点:
- private progressbar 和 private statusIV要写5次(写在MySend_XXX_ViewHolder类)
- 右边要为了上传的进度控件要复制粘贴多次findSubmitStatusViewById 和 diaplaySubmitStatusView
- 拓展性差,如果在别的场景假如有多种位置的Item,要多写很多类代码
老方案2:左右都用TextHolder;TextHolder包含private progressbar 和 private statusIV;然后TextHolder有个isRight 的 boolean字段
缺点:
- private progressbar 和 private statusIV要写5次(在TextHolder类里写)
- 右边要为了上传的进度控件要复制粘贴多次findSubmitStatusViewById 和 diaplaySubmitStatusView
一切的原因,都是java 和 oc不支持多继承,要是有多继承,可以让MySend_Text_ViewHolder extend BaseTextHolder,SubmitStatusHolder多好
下面使用策略模式,很好的解决了这些问题,代码实现完美封装(以下只拿Text文本消息来举例)
//聊天Item的位置Interface(如果是我发出的,就在右边;我收到的消息,在左边)
public interface IBubbleDirection {
//在getView()方法里的 convertView == null里触发个方法
public void findChildView(View convertView);
//在getView()方法里 显示上传View的值
public void display(int submitStatus);
}
public class RightBubbleDirectionImpl implements IBubbleDirection {
private ProgressBar submitProgressBar;//上传中的进度条
private ImageView submitStatusImageView;//上传失败的感叹号
@Override
public void findChildView(View convertView) {
submitProgressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar);
submitStatusImageView = (ImageView) convertView.findViewById(R.id.msg_status_iv);
}
@Override
public void display(int submitStatus) {
switch (submitStatus) {
case ChatBean.SUCCESS: // 发送成功
submitProgressBar.setVisibility(View.GONE);
submitStatusImageView.setVisibility(View.GONE);
break;
case ChatBean.FAIL: // 发送失败
submitProgressBar.setVisibility(View.GONE);
submitStatusImageView.setVisibility(View.VISIBLE);
break;
case ChatBean.INPROGRESS: // 发送中
submitProgressBar.setVisibility(View.VISIBLE);
submitStatusImageView.setVisibility(View.GONE);
break;
}
}
}
public class ChatListAdapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
case MESSAGE_TYPE_RECV_TXT://我接受的文本消息
case MESSAGE_TYPE_SENT_TXT:{//我发出的文本消息
TextViewHolder holder;
if (convertView == null) {
holder = new TextViewHolder(
type == MESSAGE_TYPE_SENT_TXT ? new RightBubbleDirectionImpl() : new LeftBubbleDirectionImpl(),
new TextBubbleViewImpl(myUserPhoto, onChatActionListener, mOnLinkClickListener));
convertView = mInflater.inflate(type == MESSAGE_TYPE_SENT_TXT ? R.layout.chatitem_sent_message : R.layout.chatitem_received_message, null);
//让holder去findViewById
holder.findChildView(convertView);
convertView.setTag(holder);
} else {
holder = (TextViewHolder) convertView.getTag();
}
holder.display(position, bean);
}
break;
}
//接受-文本-Text ; 其实这里无需 extends BaseTextViewHolder
public static class TextViewHolder extends BaseTextViewHolder{
private IBubbleDirection bubbleDirection;//上传progress和statusiv控件
private IBubbleView bubbleView;//文本Item控件
public TextViewHolder(IBubbleDirection bubbleDirection, IBubbleView bubbleView){
this.bubbleDirection = bubbleDirection;
this.bubbleView = bubbleView;
}
public void findChildView(View convertView){
//初始化Item自己的view
bubbleView.findChildView(convertView);
//初始化上传状态View
bubbleDirection.findChildView(convertView);
}
public void display(int position, ChatBean chatBean){
//处理Item自己的view
bubbleView.display(position, chatBean);
//处理上传状态View
displaySubmitView(chatBean.getState());
}
//因为外部ac可能要重置上传状态,所以这里设置为public
public void displaySubmitView(int submitStatus){
//处理上传状态View
bubbleDirection.display(submitStatus);
}
}
总结:在什么情况下适合使用 桥接模式
- 你希望双继承的时候:比如聊天的ViewHolder,“我发出的图片消息” 既想extend BaseImageViewHolder,又想 extend BaseUploadViewHolder
- 你想创建N个对象,这N个对象有若干个共同的特点(或者说方法) :比如
文字消息ViewHolder
,无论左右,他的View的都是普通文字(这是 文字消息的共同特点);同时我发出的消息ViewHolder
又有个共同特点:都有progress 和 statusImageView
以上,我们就可以把其中一组特点
(比如 发出的消息),抽成一个接口,然后用RightViewHolderImpl实现这个接口;然后安心搞好 TextViewHolder、ImageViewHolder就好了 - 关于
桥接模式
和策略模式
的区别:
下面是桥接模式:
//桥接模式:注意这里,IBubbleDirection是由父类控制的
public abstract class FatherTextViewHolder {
private IBubbleDirection bubbleDirectionInterFace
public FatherTextViewHolder(IBubbleDirection bubbleDirectionInterFace) {
this.bubbleDirectionInterFace = bubbleDirectionInterFace
}
public void fatherDisplay(){
bubbleDirectionInterFace.display()
}
}
//桥接模式中,子类无需关心接口的实现方式,由父类实现
class ChildTextViewHolder extend FatherTextViewHolder{
override
public void fatherDisplay(){
super.fatherDisplay()
//TODO 子类自己的代码
}
}
//桥接模式与策略模式区别就在于:他多了父类这一步,在父类中实现接口;而策略模式没有父类
class ChildTextViewHolder2 extend FatherTextViewHolder{
override
public void fatherDisplay(){
super.fatherDisplay()
//TODO 子类自己的代码
}
}
下面是策略模式:
//策略模式要比桥接简单一下,就单纯的一层
public class TextViewHolder {
private IBubbleDirection bubbleDirectionInterFace
public TextViewHolder(IBubbleDirection bubbleDirectionInterFace) {
this.bubbleDirectionInterFace = bubbleDirectionInterFace
}
public void myDisplay(){
bubbleDirectionInterFace.display()
//TODO 自己的代码
}
}
网友评论