享元模式--拒绝多对象,优化第一步(结构型模式05)

本文介绍了享元模式的概念、原理及应用场景,并通过一个具体的购票系统案例展示了如何利用享元模式优化程序性能,减少对象创建,节省内存资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是享元模式?
使用共享对象可有效地支持大量的细粒度对象。
享元模式(FlyWeight pattern)是对象池的一种实现,代表轻量级的思想。适合用在大量重复对象的创建,从而实现内存的优化,提升性能。比如我们要设计个游戏,里边要创建成千上万的士兵角色,我们也许会做一千次new soldier(),但是这样的话对于内存来说会有不必要的消耗,享元模式就很好的解决了这个问题。
享元模式中可共享不随环境改变而改变的对象叫做内部状态,随环境改变而改变的称为外部状态。

享元模式适用场景
系统中存在大量相似对象
对象没有过多的自定义特征
需要缓冲池的系统

享元模式中的角色
FlyWeight:享元对象抽象基类或者接口
ConcreteFlyWeight:具体享元对象
FlyWeightFactory:享元工厂,负责享元对象池和享元对象的创建

享元模式用例
春节回家抢票,每个人都会通过网络向服务器发抢票信息,数以万计的人同时向服务器发出查询余票的信息时,假如服务端每次都创建对象来处理这个请求,也许他会崩溃的更快…优化方法就是使用享元模式把特定的请求缓存在享元对象池中,有了就不必重建,没有再考虑新建。比如1000个用户都在查询北京-郑州的票,使用缓冲池后都从缓冲池中操作,系统处理了这1000个人的查询信息,而新建的只有这一个对象,避免了给内存加额外负担。

UML类图
这里写图片描述
ITicket接口类:

public interface ITicket{
    public void showTicketInfo(String bunk);
}

TrainTicket实现类:

public class TrainTicket implements ITicket {
    private String from;
    private 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) {
        //这里使用不大于300的随机数模仿票价
        price = new Random().nextInt(300);
        System.out.println("购买从"+from+"到"+to+"的"+bunk+"火车票"+",价格为:"+price);
    }

}

TicketFactory类:

public class TicketFactory {
    static Map<String,ITicket> mTicketMap = new HashMap<>();
    public static ITicket getTicket(String from,String to){
        String key = from+"-"+to;
        if(mTicketMap.containsKey(key)){
            System.out.println("使用缓存--》"+key);
            return mTicketMap.get(key);
        }else{
            System.out.println("新建对象--》"+key);
            ITicket ticket= new TrainTicket(from,to);
            mTicketMap.put(key, ticket);
            return ticket;
        }
    }
}

主类调用:

public class Test {

    public static void main(String[] args) {
        ITicket ticket0 = TicketFactory.getTicket("郑州", "北京");
        ticket0.showTicketInfo("硬座");

        ITicket ticket1 = TicketFactory.getTicket("郑州", "北京");
        ticket0.showTicketInfo("上铺");

        ITicket ticket2 = TicketFactory.getTicket("郑州", "北京");
        ticket0.showTicketInfo("硬卧");
    }

}

测试结果:

新建对象--》郑州-北京
购买从郑州到北京的硬座火车票,价格为:209
使用缓存--》郑州-北京
购买从郑州到北京的上铺火车票,价格为:77
使用缓存--》郑州-北京
购买从郑州到北京的硬卧火车票,价格为:272

总结
我们在java中的String定义也是使用到了享元模式,比如

String s  = "123";与String s2 = "12"+"3";
//这里如果判断s == s2;是会返回true的结果的,他们引用的是同一内存地址,但是如果使用new来创建就另论了

享元模式的优点:
大大减少程序对象的创建,降低程序内存占用,优化程序性能。
缺点:
享元模式使得系统更为复杂。为了让对象可以共享,需要将一些状态外部化,使得程序的逻辑复杂。
读取外部状态时间效率也有所下降。比如上边订票中,内部状态就是from和to。外部状态是bunk和price,出发地和目的地不变,坐席类型和价格的选择会相应改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值