广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java设计模式之享元模式
  • 844
分享到

Java设计模式之享元模式

2024-04-02 19:04:59 844人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

本文通过优化买票的重复流程来说明享元模式,为了加深对该模式的理解,会以String和基本数据类型的包装类对该模式的设计进一步说明。 读者可以拉取完整代码到本地进行学习,实现代码均测试

本文通过优化买票的重复流程来说明享元模式,为了加深对该模式的理解,会以String和基本数据类型的包装类对该模式的设计进一步说明。

读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云,本地源码下载。

一、引出问题

鉴于小王之前的优质表现,老王决定带小王出去旅游一下,但在火车站买票时却陷于了长长的队伍。

老王注意到,每次售票员卖票时都重新走一遍卖票的所有流程,很明显,如果始发地和目的地如果一样的成人票和儿童票是可以复用流程的,如果复用的话就可以大大提高卖票效率。

二、概念和使用

上面所说的复用流程实际上就是享元模式的设计思想,它是构造型设计模式之一,它通过共享数据使得相同对象在内存中仅创建一个实例,以降低系统创建对象实例的性能消耗。

享元模式包含三个角色:

(1)抽象享元Flyweight类:享元对象抽象基类或接口。

(2)具体享元ConcreteFlyweight类:实现抽象享元类。

(3)享元工ctory类:厂FlyweightFa享元模式的核心模块,负责管理享元对象池、创建享元对象,保证享元对象可以被系统适当地共享。

当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象,如果已有,享元工厂角色就提供这个已有的享元对象;如果没有就创建一个。

老王基于享元模式开发了一套卖票系统,如果起点和终点一样,成人票和儿童票就可以复用一套流程。

抽象享元类:


public interface Ticket {
    //显示票价,参数为列车类型
    public void showPrice(String type);

}

具体享元实现类:


public class ConcreteTicket implements Ticket{

    String from;
    String to;
    public ConcreteTicket(String from,String to){
        this.from = from;
        this.to = to;
    }

    @Override
    public void showPrice(String type) {
        if(type.equals("adult")){
            System.out.println("从"+from+"到"+to+"的成人票价为200元");
        }else{
            System.out.println("从"+from+"到"+to+"的儿童票价为100元");
        }

    }
}

享元工厂类:


public class TicketFactory {

    static Map<String,Ticket> map= new ConcurrentHashMap< String,Ticket >();

    public static Ticket getTicket(String from,String to){
        String key = from+to;
        if(map.containsKey(key)){
            System.out.println("使用缓存"+key);
            return map.get(key);
        }else{
            System.out.println("创建对象"+key);
            Ticket ticket = new ConcreteTicket(from,to);
            map.put(key, ticket);
            return ticket;
        }
    }

}

客户端调用:


public class Client {
    public static void main(String[] args) {
        //使用时
        TicketFactory.getTicket("南京","杭州").showPrice("adult");
        TicketFactory.getTicket("南京","杭州").showPrice("children");
    }
}

上面例子是享元模式实现的典型案例。核心其实就是享元工厂类,享元工厂类设置一个缓存池,根据条件判断是否属于一个对象,如果是一个对象就不再重新创建,直接使用缓存池中的。

三、运用

1、jdk中的String就是典型的采用的享元模式的思想。

Java中将String类定义为final(不可改变的),JVM字符串一般保存在字符串常量池中,java会确保一个字符串在常量池中只有一个拷贝,这个字符串常量池在JDK6.0以前是位于常量池中,位于永久代,而在JDK7.0中,JVM将其从永久代拿出来放置于堆中。

创建一个字符串有两种方式,一种是直接String="hello",另外一种是String s =new String("hello"),第一种是直接在字符串常量池声明一个变量,第二种方式除了是一个堆中的普通对象以外,还会在字符串常量池保存一份。

我们经常使用的一些基本数据类型的包装类实际上也使用了享元模式。我们以Integer 举例,其他包装类类似。

当我们声明一个变量时,使用Integer i1 = 88,编译器是不会报错的,在这Java上面的一个概念就叫自动装箱,编译器会自动 使用valueOf()方法创建一个Integer对象并把值赋给该对象。

查看valueOf()方法,如下:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Integer 使用享元模式的核心就在于IntegerCache,它是Integer 的一个内部类。

这里的 IntegerCache 相当于享元设计模式中的享元对象工厂类,既然是享元对象工厂类就一定会有判定一个对象是否一样的条件。

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];
    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFORMatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }
    private IntegerCache() {}
}

通过源码我们可以看到,IntegerCache 的判定一个对象是否是同一个的判断标准就是,一个字节的大小(-128 到 127 之间的数据)都作为一个对象。

既然说到了自动装箱,那相对应的也一定会有自动拆箱。

当把包装器类型的变量i1,赋值给基本数据类型变量 j 的时候,触发自动拆箱操作,将 i1中的数据取出,赋值给 j,这就是自动拆箱的过程。

其他包装器类型,比如 Long、Short、Byte 等,也都利用了享元模式来缓存 -128 到 127 之间的数据。比如,Long 类型对应的 LonGCache 享元工厂类。

四、总结

享元模式与我们常说的缓存的概念很相似,总体来说还是一个很简单的设计模式,在我们实际使用中为了提高对象利用率,可以有意识的使用这种模式。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对编程网的支持。如果你想了解更多相关内容请查看下面相关链接

--结束END--

本文标题: Java设计模式之享元模式

本文链接: https://www.lsjlt.com/news/168824.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java设计模式之享元模式
    本文通过优化买票的重复流程来说明享元模式,为了加深对该模式的理解,会以String和基本数据类型的包装类对该模式的设计进一步说明。 读者可以拉取完整代码到本地进行学习,实现代码均测试...
    99+
    2022-11-13
  • javascript设计模式之享元模式
    目录一. 认识享元模式二. 代码具体实现1. 不使用享元模式实现上述案例2. 使用享元模式重构上述代码3. 享元模式的状态三. 享元模式实际应用扩展:再谈内部状态和外部状态四. 对象...
    99+
    2022-11-12
  • Java设计模式之享元模式示例详解
    目录定义原理类图案例需求方案:享元模式分析总结定义 享元模式(FlyWeight Pattern),也叫蝇量模式,运用共享技术,有效的支持大量细粒度的对象,享元模式就是池技术的重要实...
    99+
    2022-11-13
  • 深入理解Java设计模式之享元模式
    目录一、引言二、什么是享元模式三、享元模式的结构四、享元模式和单例模式的异同五、享元模式的优缺点六、享元模式的使用场景七、享元模式的实现八、总结一、引言 大家都知道单例模式,通过一个...
    99+
    2022-11-12
  • 好程序员分享java设计模式之享元模式
      好程序员分享java设计模式之享元模式,享元模式有点类似于单例模式,都是只生成一个对象被共享使用。享元模式主要目的就是让多个对象实现共享,减少不必要的内存消耗,将多对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,以此来降低...
    99+
    2023-06-02
  • 每天一个设计模式之享元模式
    作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 个人技术博客-godbmw.com 欢迎来玩! ...
    99+
    2023-01-31
    模式
  • JavaScript设计模式之性能优化模式享元模式
    目录前言案例享元设计模式的状态前言 享元设计模式是用于性能优化的模式,这种设计模式的核心在于可以共享技术并支持对大量细分过后的对象进行调整,如果系统    中因为...
    99+
    2022-11-13
  • .Net结构型设计模式之享元模式(Flyweight)
    目录一、动机(Motivate)二、意图(Intent)三、结构图(Structure)四、模式的组成五、享元模式的具体代码实现六、享元模式的实现要点:1、享元模式的优点2、享元模式...
    99+
    2022-11-13
  • Java结构型设计模式之享元模式示例详解
    目录享元模式概述目的应用场景优缺点主要角色享元模式结构内部状态和外部状态享元模式的基本使用创建抽象享元角色创建具体享元角色创建享元工厂客户端调用总结享元模式实现数据库连接池创建数据库...
    99+
    2022-11-13
  • 如何理解Java设计模式的享元模式
    本篇内容介绍了“如何理解Java设计模式的享元模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、引言大家都知道单例模式,通过一个全局变量...
    99+
    2023-06-25
  • Python设计模式结构型享元模式
    目录一、享元模式二、应用场景三、代码示例一、享元模式 享元,可理解为 Python 中的元类、最小粒度的类,系统中存在大量的相似对象时,可以选择享元模式提高资源利用率。 享元具有两种...
    99+
    2022-11-13
  • .Net结构型设计模式之享元模式怎么实现
    这篇文章主要介绍了.Net结构型设计模式之享元模式怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇.Net结构型设计模式之享元模式怎么实现文章都会有所收获,下面我们一起来看看吧。一、动机(Motivate...
    99+
    2023-06-30
  • Java设计模式之单例模式
    目录什么是设计模式?单例模式是什么?单例模式设计的原则是什么?Java实现单例模式的5种方式?懒汉饿汉静态内部类双重校验锁DCL(Double Check Lock)枚举(num)总...
    99+
    2022-11-12
  • Java设计模式之桥接模式
    本文通过老王和小王买车,引出设计模式中的结构型设计之桥接模式,接着说明设计型模式的概念和代码实现,为了加深理解,会说明适配器设计模式在JDBC中的应用,最后谈谈桥接模式和适配器模式的...
    99+
    2022-11-13
  • Java设计模式之命令模式
    本文通过解决老王经常搞错借书人的问题,来引出行为型模式中的命令模式。为了在案例之上理解的更加透彻,我们需要了解命令模式在源码中的应用。最后指出命令模式的应用场景和优缺点。 读者可以拉...
    99+
    2022-11-13
  • Java设计模式之策略模式
    在一个收银系统中,如果普通用户、中级会员、高级会员分别对应着不同的优惠策略,常规编程就要使用一系列的判断语句,判断用户类型,这种情况下就可以使用策略模式。 一、概念理解 策略模式的概...
    99+
    2022-11-13
    Java 设计模式 策略模式
  • Java设计模式之状态模式
    实际开发中订单往往都包含着订单状态,用户每进行一次操作都要切换对应的状态,而每次切换判断当前的状态是必须的,就不可避免的引入一系列判断语句,为了让代码更加清晰直观,我们引入今天的主角...
    99+
    2022-11-13
    Java 设计模式 状态模式
  • Java设计模式之代理模式
    本文由老王出租房子引出——代理设计模式,将从最简单的静态代理实现开始,后延伸使用jdk实现动态代理,最后扩展到Cglib实现动态代理。为了更深入理解代理模式,...
    99+
    2022-11-13
  • Java设计模式之组合模式
    本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在...
    99+
    2022-11-13
  • Java设计模式之外观模式
    本文通过老王改造小王公司的整体架构来说明外观模式,所谓的外观模式其实就是在各种复杂的子系统中抽象出来一个接口,隐藏具体的实现细节,调用方调用时只需要调用接口即可。为了加深理解我们会选...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作