Android Ios 策略模式實戰(zhàn)使用場景

哪些常見的場景適合使用策略模式呢?我在寫聊天界面的時候遇到了一個非常適合用策略模式的地方,與大家分享 (本文以Android的聊天界面為案例,ios也是一個道理)
本文不做介紹 策略模式到底是什么,網(wǎng)上別人寫的很詳細(xì)。

聊天界面的ViewHolder (ios中叫Cell)一共有哪幾種類型?

ViewHolder 位置 內(nèi)容 上傳狀態(tài)View
MySend_Text_ViewHolder 發(fā)文字
MyReceived_Text_ViewHolder 收文字 沒有
MySend_Image_ViewHolder 發(fā)圖片
MyReceived_Image_ViewHolder 收圖片 沒有
MySend_Voice_ViewHolder 發(fā)語音條
MyReceived_Voice_ViewHolder 收語音條 沒有
MySend_Location_ViewHolder 發(fā)位置
MyReceived_Location_ViewHolder 收位置 沒有
MySend_Call_ViewHolder 發(fā)語音通話
MyReceived_Call_ViewHolder 收語音通話 沒有

老方案1:左邊是BaseTextHolder,右邊的MySend_Text_ViewHolder extend BaseTextHolder,然后加上progressbar 和 statusIV

缺點(diǎn):

  1. private progressbar 和 private statusIV要寫5次(寫在MySend_XXX_ViewHolder類)
  2. 右邊要為了上傳的進(jìn)度控件要復(fù)制粘貼多次findSubmitStatusViewById 和 diaplaySubmitStatusView
  3. 拓展性差,如果在別的場景假如有多種位置的Item,要多寫很多類代碼

老方案2:左右都用TextHolder;TextHolder包含private progressbar 和 private statusIV;然后TextHolder有個isRight 的 boolean字段

缺點(diǎn):

  1. private progressbar 和 private statusIV要寫5次(在TextHolder類里寫)
  2. 右邊要為了上傳的進(jìn)度控件要復(fù)制粘貼多次findSubmitStatusViewById 和 diaplaySubmitStatusView

一切的原因,都是java 和 oc不支持多繼承,要是有多繼承,可以讓MySend_Text_ViewHolder extend BaseTextHolder,SubmitStatusHolder多好

下面使用策略模式,很好的解決了這些問題,代碼實現(xiàn)完美封裝(以下只拿Text文本消息來舉例)

//聊天Item的位置Interface(如果是我發(fā)出的,就在右邊;我收到的消息,在左邊)
public interface IBubbleDirection {
    //在getView()方法里的 convertView == null里觸發(fā)個方法
    public void findChildView(View convertView);
    //在getView()方法里 顯示上傳View的值
    public void display(int submitStatus);
}

public class RightBubbleDirectionImpl implements IBubbleDirection {
    
    private ProgressBar submitProgressBar;//上傳中的進(jìn)度條
    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: // 發(fā)送成功
                submitProgressBar.setVisibility(View.GONE);
                submitStatusImageView.setVisibility(View.GONE);
                break;
            case ChatBean.FAIL: // 發(fā)送失敗
                submitProgressBar.setVisibility(View.GONE);
                submitStatusImageView.setVisibility(View.VISIBLE);
                break;
            case ChatBean.INPROGRESS: // 發(fā)送中
                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:{//我發(fā)出的文本消息
                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);
            //初始化上傳狀態(tài)View
            bubbleDirection.findChildView(convertView);
        }

        public void display(int position, ChatBean chatBean){
            //處理Item自己的view
            bubbleView.display(position, chatBean);
            //處理上傳狀態(tài)View
            displaySubmitView(chatBean.getState());
        }

        //因為外部ac可能要重置上傳狀態(tài),所以這里設(shè)置為public
        public void displaySubmitView(int submitStatus){
            //處理上傳狀態(tài)View
            bubbleDirection.display(submitStatus);
        }
    }

總結(jié):在什么情況下適合使用 橋接模式

  1. 你希望雙繼承的時候:比如聊天的ViewHolder,“我發(fā)出的圖片消息” 既想extend BaseImageViewHolder,又想 extend BaseUploadViewHolder
  2. 你想創(chuàng)建N個對象,這N個對象有若干個共同的特點(diǎn)(或者說方法) :比如 文字消息ViewHolder,無論左右,他的View的都是普通文字(這是 文字消息的共同特點(diǎn));同時 我發(fā)出的消息ViewHolder 又有個共同特點(diǎn):都有progress 和 statusImageView
    以上,我們就可以把其中一組特點(diǎn) (比如 發(fā)出的消息),抽成一個接口,然后用RightViewHolderImpl實現(xiàn)這個接口;然后安心搞好 TextViewHolder、ImageViewHolder就好了
  3. 關(guān)于 橋接模式策略模式 的區(qū)別:
    下面是橋接模式:
//橋接模式:注意這里,IBubbleDirection是由父類控制的
public abstract class FatherTextViewHolder {
    private IBubbleDirection bubbleDirectionInterFace

    public FatherTextViewHolder(IBubbleDirection bubbleDirectionInterFace) {
        this.bubbleDirectionInterFace = bubbleDirectionInterFace   
    }

    public void fatherDisplay(){
        bubbleDirectionInterFace.display()
    }
}

//橋接模式中,子類無需關(guān)心接口的實現(xiàn)方式,由父類實現(xiàn)
class ChildTextViewHolder extend FatherTextViewHolder{

    override
    public void fatherDisplay(){
        super.fatherDisplay()
        //TODO 子類自己的代碼
    }
}

//橋接模式與策略模式區(qū)別就在于:他多了父類這一步,在父類中實現(xiàn)接口;而策略模式?jīng)]有父類
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 自己的代碼
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,000評論 2 59
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,834評論 28 54
  • 首先介紹下自己的背景: 我11年左右入市到現(xiàn)在,也差不多有4年時間,看過一些關(guān)于股票投資的書籍,對于巴菲特等股神的...
    瞎投資閱讀 5,936評論 3 8
  • ![Flask](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAW...
    極客學(xué)院Wiki閱讀 7,817評論 0 3
  • 不知不覺易趣客已經(jīng)在路上走了快一年了,感覺也該讓更多朋友認(rèn)識知道易趣客,所以就謝了這篇簡介,已做創(chuàng)業(yè)記事。 易趣客...
    Physher閱讀 3,811評論 1 2

友情鏈接更多精彩內(nèi)容