享元模式

一、简介

享元模式,是对象池的一种实现,主要用于减少创建对象的数量,以减少内存占用和提高性能。定义:运用共享技术有效地支持大量细粒度的对象。意思就是采用对象共享的形式来实现大量对象的情况。有大量对象的情况,有可能导致内存溢出或者重复创建之前已经创建的相同对象。

先举个简单的例子,android中的ViewHolder缓存view,为了优化性能存在一种写法,使用一个集合存储已经被实例化过的view,就不需要每次都去创建了,这就是享元模式的一种简单应用。

public abstract class RvBaseViewHolder<T> extends RecyclerView.ViewHolder {

    private SparseArray<View> mViews;

    public RvBaseViewHolder(@NonNull View itemView) {
        super(itemView);
        mViews = new SparseArray<>();
    }

    public abstract void bindData(int position, @Nullable T data);

    /**快速获取view*/
    public <V extends View> V findViewById(int viewId){
        View view = mViews.get(viewId);
        if(null == view){
            view = itemView.findViewById(viewId);
            if(null != view){
                mViews.put(viewId,view);
            }else{
                return null;
            }
        }
        return (V) view;
    }
}

二、UML图

  • Flyweight:享元模式抽象类或接口
  • ConcreateFlyweight:具体的享元对象
  • FlyweightFactory:享元工厂,负责管理享元对象池和创建享元对象

Flyweight代表轻量级的意思。

三、简单示例

过年抢票,大家肯定都不陌生,各种刷票插件、软件什么的。在用户设置好出发和到达之后,每次查询请求都返回一系列的车票结果。当数千万的用户在不断请求查询结果时,如果每次查询结果都是重新创建返回的,可想而知,肯定会有大量的重复对象的创建、销毁,内存占用和GC的压力都会随之增大。而享元模式就能很好的应对这种情况,车次都是固定的,根据出发地和到达地查询出来的车次基本都是相同的(当然你还可以添加更多的筛选条件)。

我们可以将这些共享的对象缓存起来,用户查询时优先使用缓存,如果没有缓存则重新创建,这样就不必要在重复创建和销毁对象了。

首先,创建一个Ticket接口,定义输出车票信息的方法

public interface Ticket {
    public void showTicketInfo(String info);
}

再是具体的实现TrainTicket

public class TrainTicket implements Ticket {
    //出发地
    private final String from;
    //到达地
    private final String to;
    //铺位
    private String bunk;
    //价格
    private int price;

    public TrainTicket(String from, String to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public void showTicketInfo(String bunk) {
        price = new Random().nextInt(200);
        System.out.println("查询 从 "+from+" 到 " + to + " 的 " + bunk + " 车票,价格:" + price);
    }
}

接着就是TicketFactory类,不同于之前的工厂模式,工厂模式每个返回的对象都是新创建的,而享元模式需要做缓存,具体代码如下:

public class TicketFactory {
    private static Map<String,Ticket> ticketMap = new ConcurrentHashMap<>();

    public static Ticket getTicket(String from,String to){
        final String key = from + "-" + to;
        if(ticketMap.containsKey(key)){
            return ticketMap.get(key);
        }else{
            Ticket ticket = new TrainTicket(from, to);
            ticketMap.put(key,ticket);
            return ticket;
        }
    }
}

这就面了,每次获取车票对象时的创建,享元模式有效的减少了重复对象的创建。

四、总结

享元模式还是比较简单的,在创建重复对象的情况中大大降低了内存的消耗,提高了程序的性能。同时也提高了系统的复杂性,需要分离出外部状态和内部状态,而且外部状态应具有固化性,不应该随内部状态改变而改变,这样就使得程序变的很混乱。

 

——————————————————————————————————
作者:MrTrying
链接:https://www.jianshu.com/p/35030da907ce
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值