設計模式——享元模式

定義

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

模板

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

實例

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

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

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. 大部分的對象能夠按照內部狀態進行分組

其它實例:
棋類遊戲ui

相關文章
相關標籤/搜索