定義
享元(Flyweight)模式的定義:運用共享技術來有効地支持大量細粒度對象的複用。它通過共享已經存在的又橡來大幅度減少需要創建的對象數量、避免大量相似類的開銷,從而提高系統資源的利用率。
模板
- FlyweightFactory享元工廠類:創建並管理享元對象,享元池一般設計成鍵值對
- FlyWeight抽象享元類:通常是一個接口或抽象類,聲明公共方法,這些方法可以向外界提供對象的內部狀態,設置外部狀態。
- ConcreteFlyWeight具體享元類:爲內部狀態提供成員變量進行存儲
- 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);
}
}
}
優點
相同對象只要保存一份,這降低了系統中對象的數量,從而降低了系統中細粒度對象給內存帶來的壓力。
缺點
爲了使對象可以共享,需要將一些不能共享的狀態外部化,這將增加程序的複雜性。
讀取享元模式的外部狀態會使得運行時間稍微變長。
適用場景
- 程序中有大量相同或者相似對象,這些對象耗費大量的內存資源
- 大部分的對象可以按照內部狀態進行分組
其它實例:
棋類遊戲