设计模式——享元模式
定义
享元(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);
}
}
}
优点
相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
缺点
为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
读取享元模式的外部状态会使得运行时间稍微变长。
适用场景
- 程序中有大量相同或者相似对象,这些对象耗费大量的内存资源
- 大部分的对象可以按照内部状态进行分组
其它实例:
棋类游戏
梦想不是浮躁,而是沉淀和积累