设计模式——享元模式

ⅰ亾dé卋堺 提交于 2019-12-04 15:06:09

定义

享元(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. 大部分的对象可以按照内部状态进行分组

其它实例:
棋类游戏

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!