装饰者模式—对象也能换装啦

1.概念

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。是继承关系的一个替代方案。

2.针对问题

动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。不改变接口的前提下,增强所考虑的类的性能。
何时使用:
    1)需要扩展一个类的功能,或给一个类增加附加责任。
    2)需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
    3)需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承变得 不现实。

3.结构

在这里插入图片描述
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类
装饰角色(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
具体装饰角色(ConcreteDecorator):负责给构件对象“贴上”附加的责任

4.例子

做一个普通的内存缓存对象,并且对缓存进行扩展,使得普通缓存拥有FIFO和LFU的功能。
FIFO(First in First out),先进先出。
LFU(Least Frequently Used)最近最少使用算法。

1:cache 缓存接口

public interface Cache {

    String getId();

    void putObject(Object key, Object value);

    Object getByKey(Object key);

    Object removeByKey(Object key);

    void clear();

    int getSize();

}

2.PerpetualCache 普通的缓存对象

public class PerpetualCache implements Cache {

    private final String id;

    private final Map<Object, Object> cache = new HashMap<>();

    public PerpetualCache(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        cache.put(key, value);
    }

    @Override
    public Object getByKey(Object key) {
        return cache.get(key);
    }

    @Override
    public Object removeByKey(Object key) {
        return cache.remove(key);
    }

    @Override
    public void clear() {
        cache.clear();
    }

    @Override
    public int getSize() {
        return cache.size();
    }
}

3.Decorator 装饰者接口

public interface Decorator extends Cache {
}

4.装饰对象

FIFO
public class FifoCache implements Decorator {

    private final Cache delegate;
    private final Deque<Object> keyList;
    private int size;

    public FifoCache(Cache delegate) {
        this.delegate = delegate;
        this.keyList = new LinkedList<>();
        this.size = 1024;
    }

    @Override
    public String getId() {
        return delegate.getId() + "fifo";
    }

    @Override
    public void putObject(Object key, Object value) {
        cycleKeyList(key);
        delegate.putObject(key, value);
    }

    @Override
    public Object getByKey(Object key) {
        return delegate.getByKey(key);
    }

    @Override
    public Object removeByKey(Object key) {
        return delegate.removeByKey(key);
    }

    @Override
    public void clear() {
        delegate.clear();
        keyList.clear();
    }

    @Override
    public int getSize() {
        return delegate.getSize();
    }

    private void cycleKeyList(Object key) {
        keyList.addLast(key);
        if (keyList.size() > size) {
            Object oldestKey = keyList.removeFirst();
            delegate.removeByKey(oldestKey);
        }
    }
}
LRU
public class LruCache implements Decorator {

    private final Cache delegate;
    private Map<Object, Object> keyMap;
    private Object eldestKey;

    public LruCache(Cache delegate) {
        this.delegate = delegate;
        setSize(1024);
    }

    @Override
    public String getId() {
        return delegate.getId() + "lru";
    }

    @Override
    public void putObject(Object key, Object value) {
        delegate.putObject(key, value);
        cycleKeyList(key);
    }

    @Override
    public Object getByKey(Object key) {
        keyMap.get(key); // touch
        return delegate.getByKey(key);
    }

    @Override
    public Object removeByKey(Object key) {
        return delegate.removeByKey(key);
    }

    @Override
    public void clear() {
        delegate.clear();
        keyMap.clear();
    }

    @Override
    public int getSize() {
        return delegate.getSize();
    }

    private void cycleKeyList(Object key) {
        keyMap.put(key, key);
        if (eldestKey != null) {
            delegate.removeByKey(eldestKey);
            eldestKey = null;
        }
    }

    public void setSize(final int size) {
        keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
            private static final long serialVersionUID = 4267176411845948333L;

            @Override
            protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
                boolean tooBig = size() > size;
                if (tooBig) {
                    eldestKey = eldest.getKey();
                }
                return tooBig;
            }
        };
    }

}

测试

public static void main(String[] args) {

    PerpetualCache cache = new PerpetualCache("cache");
    // 装饰先进先出
    FifoCache fifoCache = new FifoCache(cache);
    System.out.println("fifo" + fifoCache.getId());

    // 装饰lru
    LruCache lruCache = new LruCache(cache);
    System.out.println("lru" + lruCache.getId());
}

在这里插入图片描述

了解更多请关注微信公众【摩登猪头】,和作者互动,答疑等。公众号上准备了大量的资源等你来领取。你的关注是作者创作的动力。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值