• 设计模式——享元模式


    定义

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

    其它实例:
    棋类游戏

  • 相关阅读:
    Python中的返回函数与闭包
    Python的高阶函数小结
    Python的生成器Generator小结
    Vim插件YCM的安装
    用Vundle管理Vim插件
    声卡(Sound Card)基本概念
    Linux中Source的用法
    js 的执行过程
    mongoose@4.5.2的eachAsync bug
    [mongodb] MMAP 和wiredTiger 的比较
  • 原文地址:https://www.cnblogs.com/NeilZhang/p/11838662.html
Copyright © 2020-2023  润新知