简述-享元模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ddxxii/article/details/83043420

介绍

享元的主旨在共享,既然共享了,那么就好处就是可以复用了,它的英文名叫Flyweight,轻量级的意思,通过共享的方式来节省内存开销。

其目的是达到部分状态可共享,可共享的状态为内部状态(不随外部环境改变),不可共享为外部状态(可随外部环境改变)。原理即是做缓存对象处理。

比如Android中的Message,推荐使用handler的obtain方法来获取一个message,这种方式获取的message是从message池里获取出来使用的,当使用完成之后,又recycle放回message池里,默认池大小为50,回收的时候,如果池里小于50个则放入池中,使用时从中取出,Message是使用链表方式存储。

UML

使用场景

  • 系统中存在大量相似对象
  • 细粒度对象有较接近的外部状态,且与内部状态无关,也就是说对象没有特定身份(就像Message,外部都是Message,内部携带的值完全可变)
  • 需要缓冲池的场景

事例

就比如系统中有消息对象到处都需要使用,那么就满足来系统中存在大量相似的对象,就可以采用缓存策略来节省内存了

  1. 建立消息接口:提供更改内部消息,和获取消息方法
/**
 * 享元模式
 */
public interface IMessage {
    /**
     * 设置消息对象携带的消息
     *
     * @param info
     */
    void setInfo(String info);

    /**
     * 获取消息
     */
    String getInfo();
}
  1. 消息实体,实现消息接口

/**
 * 享元模式消息对象
 */
public class Message implements IMessage {
    private String info;

    @Override
    public void setInfo(String info) {
        this.info = info;
    }


    @Override
    public String getInfo() {
        return this.info;
    }
}
  1. 建立工厂接口:提供回收消息方法,获取消息方法
/**
 * 享元模式工厂:
 * 1.取缓存对象,存缓存对象
 * 2. 回收缓存对象
 */
public interface IMessageFactory {
    /**
     * 消息对象使用完后,进行回收可再利用
     */
    void recycle(IMessage iMessage);

    /**
     * 获取一个消息对象
     *
     * @return 消息对象
     */
    IMessage obtainMessage();
}

  1. 建立实体工厂:该工厂全局使用,用了单例模式,内部使用一个列表来进行缓存,列表缓存数量控制为2个
/**
 * 消息缓存工厂
 */
public class MessageFactory implements IMessageFactory {
    /**
     * 缓存的列表
     */
    private List<IMessage> messageCacheList = new ArrayList<>(2);

    public static IMessageFactory getInstance() {
        return MyHolder.MESSAGE_FACTORY;
    }

    /**
     * 回收,加到列表中,可再复用
     *
     * @param iMessage
     */
    @Override
    public void recycle(IMessage iMessage) {
        synchronized (messageCacheList) {
            messageCacheList.add(iMessage);
        }
    }

    /**
     * 获取消息对象
     *
     * @return 缓存的消息对象或者是新建的消息对象
     */
    @Override
    public IMessage obtainMessage() {
        synchronized (messageCacheList) {
            if (messageCacheList.size() > 0) {
                System.out.println("缓存有数据,从缓存中获取");
                return messageCacheList.remove(0);
            }
            System.out.println("缓存没数据,新建返回");
            IMessage iMessage = new Message();
            return iMessage;
        }
    }

    private static class MyHolder {
        private static final MessageFactory MESSAGE_FACTORY = new MessageFactory();
    }
}
  1. 测试Client
public static void main(String[] arg) {
        System.out.println("获取+回收");
        for (int i = 0; i < 3; i++) {
            //获取消息并回收
            IMessage iMessage = MessageFactory.getInstance().obtainMessage();
            iMessage.setInfo("消息" + i);
            System.out.println(iMessage.getInfo());
            MessageFactory.getInstance().recycle(iMessage);
        }
        System.out.println("只获取");
        //只获取不回收
        for (int i = 0; i < 3; i++) {
            //获取消息并回收
            IMessage iMessage = MessageFactory.getInstance().obtainMessage();
            iMessage.setInfo("消息" + i);
            System.out.println(iMessage.getInfo());
        }

    }
    
  1. 输出
获取+回收
缓存没数据,新建返回
消息0
缓存有数据,从缓存中获取
消息1
缓存有数据,从缓存中获取
消息2
只获取
缓存有数据,从缓存中获取
消息0
缓存没数据,新建返回
消息1
缓存没数据,新建返回
消息2

通过一个列表来缓存,使用完了进行回收,这样就达到了一个简单的消息缓存操作,也可以控制缓存的量。

总结:享元模式的实现方式多种多样,Android中的Message就在Message对象中实现了recycle方法,通过链表方式引用缓存对象。主要是一个思想,目的是一样的,就是达到缓存共享复用

猜你喜欢

转载自blog.csdn.net/ddxxii/article/details/83043420