設計模式——享元模式

定義

享元(Flyweight)模式的定義:運用共享技術來有効地支持大量細粒度對象的複用。它通過共享已經存在的又橡來大幅度減少需要創建的對象數量、避免大量相似類的開銷,從而提高系統資源的利用率。

模板

  1. FlyweightFactory享元工廠類:創建並管理享元對象,享元池一般設計成鍵值對
  2. FlyWeight抽象享元類:通常是一個接口或抽象類,聲明公共方法,這些方法可以向外界提供對象的內部狀態,設置外部狀態。
  3. ConcreteFlyWeight具體享元類:爲內部狀態提供成員變量進行存儲
  4. UnsharedConcreteFlyWeight非共享享元類:不能被共享的子類可以設計爲非共享享元類

實例

看下面一張普通的快遞列表頁面:

該列表中有兩種內容: 一種是快遞信息行 另一種是 標題行(大些字母表示的用於分類的)。對於這樣一個頁面:
ConcreteFlyWeight部分: 兩類信息的view佈局
UnsharedConcreteFlyWeight: 標題內容/快遞名稱及圖片

android中對於列表的view複用已經封裝在ListView/RecyclerView中,業務只需要實現相應的接口即可實現佈局的複用,但這裏複用的核心思想就是 “享元模式”。 具體的實現與分析,見下面的代碼

public class ExpressAdapter extends RecyclerView.Adapter {

    // 定義兩種類型的item
    private static final int TYPE_TITLE = 1;
    private static final int TYPE_CONTENT = 2;

    private Context mContext;
    // 保存有 每一行信息的list,每個ItemInfo有種類。 相當於UnsharedConcreteFlyWeight
    // 不可服用
    private List<ItemInfo> mItemInfoList;
    
    public LanguageManagerAdapter(Context context) {
        this.mContext = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // 創建可以共享兩種類型視圖的view:相當於FlyweightFactory
        if (viewType == TYPE_CONTENT) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_language_mgr_lang, parent, false);
            return new ContentViewHolder(view);
        } else if (viewType == TYPE_TITLE) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_language_mgr_title, parent, false);
            return new TitleViewHolder(view);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        // // 將數據部分設置到佈局視圖中
        if (holder instanceof ContentViewHolder) {
            fillLabelData((ContentViewHolder) holder, position);
        } else if (holder instanceof TitleViewHolder) {
            fillTitleData((TitleViewHolder) holder, position);
        }
    }

    @Override
    public int getItemCount() {
        return mItemInfoList.size();
    }

    @Override
    public int getItemViewType(int position) {
        ItemInfo ItemInfo = mItemInfoList.get(position);
        int type = ItemInfo.getType();
        switch (type) {
            case ItemInfo.ITEM_TYPE_TITLE:
                return TYPE_TITLE;
            case ItemInfo.ITEM_TYPE_CONTENT:
                return TYPE_CONTENT;
            default:
                break;
        }
        return super.getItemViewType(position);
    }

    //相當於ConcreteFlyWeight
    static class ContentViewHolder extends RecyclerView.ViewHolder {
        TextView mContent;

        ContentViewHolder(View view) {
            super(view);
            mContent = view.findViewById(R.id.content);
        }
    }

    //相當於ConcreteFlyWeight
    static class TitleViewHolder extends RecyclerView.ViewHolder {
        TextView mTvTitle;

        TitleViewHolder(View itemView) {
            super(itemView);
            mTvTitle = itemView.findViewById(R.id.tv_title);
        }
    }

}

優點

 相同對象只要保存一份,這降低了系統中對象的數量,從而降低了系統中細粒度對象給內存帶來的壓力。

缺點

爲了使對象可以共享,需要將一些不能共享的狀態外部化,這將增加程序的複雜性。
讀取享元模式的外部狀態會使得運行時間稍微變長。

適用場景

  1. 程序中有大量相同或者相似對象,這些對象耗費大量的內存資源
  2. 大部分的對象可以按照內部狀態進行分組

其它實例:
棋類遊戲

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章