设计模式系列(结构型模式)之五 享元模式

享元模式

提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象。

适用于:
底层系统开发,解决性能问题;
系统拥有大量相似对象,需要缓冲池的场景。

优点:
相同对象只要保存一份,这降低了系统中对象的数量,从而降低内存占用

缺点:
关注内/外部状态,关注线程安全问题;
程序的逻辑复杂化。

享元模式中存在以下两种状态:
内部状态,即不会随着环境的改变而改变的可共享部分,可以简单理解为享元对象的属性状态
外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。可以简单理解为方法参数

享元模式的主要角色有如下。
抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

1.制作水果沙拉,创建一个沙拉接口,里面有个添加水果的方法

public interface Salad {
    public void add();
}

2.创建具体的实现类水果沙拉 里面有水果的名字和添加的时间两个属性,重新添加方法

public class FruitSalad implements Salad {
    private String name;
    private LocalDateTime  addTime;
    public FruitSalad(String name) {
        this.name = name;
    }
    public void setAddTime(LocalDateTime  addTime){
        this.addTime=addTime;
    }
    @Override
    public void add() {
        try {
            Thread.sleep(100);
            System.out.println("添加"+name+",添加时间为"+addTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3.创建生产水果沙拉的工厂类FruitFactory ,代码关键是通过HashMap存储对象,实现共享。

public class FruitFactory {
    private static final HashMap<String,FruitSalad> map=new HashMap();
    public static FruitSalad produce(String name){
        FruitSalad fruitSalad=map.get(name);
        if(fruitSalad==null){
            System.out.println("没有"+name+"材料,去冰箱里拿");
            fruitSalad=new FruitSalad(name);
            map.put(name,fruitSalad);
        }
        return fruitSalad;
    }
}

4.测试输出

public class Test {
    private static final String[] FRUIT = {"苹果", "香蕉", "草莓"};
    public static void main(String[]args){
        IntStream.range(0, 5).forEach((i) -> {
            String name = FRUIT[(int) (Math.random() * FRUIT.length)];//随机取数
            FruitSalad fruitPie = FruitFactory.produce(name);
            fruitPie.setAddTime(LocalDateTime.now());
            fruitPie.add();
        });
    }
}
/*
没有苹果材料,去冰箱里拿
添加苹果,添加时间为2020-08-31T13:14:24.176
没有草莓材料,去冰箱里拿
添加草莓,添加时间为2020-08-31T13:14:24.278
没有香蕉材料,去冰箱里拿
添加香蕉,添加时间为2020-08-31T13:14:24.378
添加香蕉,添加时间为2020-08-31T13:14:24.479
添加草莓,添加时间为2020-08-31T13:14:24.580
*/

从上面的输出看,在5次循环中,只生产了3个材料对象,大概的描述了系统有大量相似对象的时候,需要缓冲池的场景。
JDK中的字符串常量池,数据库连接池等都是用的享元模式。下一篇讲讲组合模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值