二哈谈设计模式之享元模式

享元模式



前言

– 场景:
内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的
对象,我们可以通过享元模式,节省内存。
– 核心:
享元模式以共享的方式高效地支持大量细粒度对象的重用。
享元对象能做到共享的关键是区分了内部状态和外部状态。
内部状态:可以共享,不会随环境变化而改变
外部状态:不可以共享,会随环境变化而改变

– 享元模式实现:

  • FlyweightFactory享元工厂类
    创建并管理享元对象,享元池一般设计成键值对
  • FlyWeight抽象享元类
    通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。
  • ConcreteFlyWeight具体享元类
    为内部状态提供成员变量进行存储
  • UnsharedConcreteFlyWeight非共享享元类
    不能被共享的子类可以设计为非共享享元类

一、具体实现

以咖啡店为例,咖啡店有几种口味的咖啡,拿铁、摩卡、卡布奇诺…如果店家接到订单要十几杯咖啡,显然咖啡的口味可以设置为共享的,而不必每一杯单独生成。

1.抽象享元对象

/**
 * 抽象享元对象
 */
public abstract class Order {
    //卖出的动作
    public abstract void sell();
}

2.具体享元角色

/**
 *具体享元角色
 */
public class FlavorOrder extends Order{
    public String flavor;

    //获取咖啡口味
    public FlavorOrder(String flavor) {
        this.flavor = flavor;
    }

    @Override
    public void sell() {
        System.out.println("卖出一杯"+flavor+"的咖啡");
    }
}

3.享元工厂角色

/**
 * 享元工厂角色
 */
public class FlavorFactory {
    private Map<String,Order> flavorPool = new HashMap<>();

    //静态工厂,负责生成订单
    private static  FlavorFactory flavorFactory = new FlavorFactory();

    private FlavorFactory(){}

    public static FlavorFactory getInstance(){
        return flavorFactory;
    }

    public Order getOrder(String flavor){
        Order order = null;
        //实现享元模式关键
        if(flavorPool.containsKey(flavor)){
            order= flavorPool.get(flavor);
        }else {
            order = new FlavorOrder(flavor);
            flavorPool.put(flavor,order);
        }
        return order;
    }

    public int getTotalFlavorMade(){
        return flavorPool.size();
    }
}

4.测试类

/**
 * 客户类
 */
public class Client {

    //下订单
    private static List<Order> orders = new ArrayList<>();

    //订单对象生成工厂
    private static FlavorFactory flavorFactory;

    //增加订单
    private static void takeOrders(String flavor){
        orders.add(flavorFactory.getOrder(flavor));
    }

    public static void main(String[] args) {
        flavorFactory = FlavorFactory.getInstance();
        //增加订单
        takeOrders("摩卡");
        takeOrders("卡布奇诺");
        takeOrders("香草星冰乐");
        takeOrders("拿铁");
        takeOrders("拿铁");
        takeOrders("摩卡");

        //卖咖啡
        for (Order order : orders) {
            order.sell();
        }

        System.out.println("客户一共买了"+orders.size()+"杯咖啡");

        System.out.println("共生成了"+flavorFactory.getTotalFlavorMade()+"个对象");
    }

}

结果:
在这里插入图片描述


二、应用场景

  • 线程池、数据库连接池。
  • String类的设计也是享元模式

总结

  • 优点
    1.极大减少内存中对象的数量
    2.相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
    3.外部状态相对独立,不影响内部状态
  • 缺点
    1.模式较复杂,使程序逻辑复杂化
    2.为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长。用时间换取了空间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值