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