享元模式与组合模式(3)

简介: 享元模式与组合模式(3)

//客户端类


public class Client {
    public static void main(String[] args) {
        List<Character> compositeState = new ArrayList<Character>();
        compositeState.add('a');
        compositeState.add('b');
        compositeState.add('c');
        compositeState.add('a');
        compositeState.add('b');
        FlyweightFactory flyFactory = new FlyweightFactory();
        Flyweight compositeFly1 = flyFactory.factory(compositeState);
        Flyweight compositeFly2 = flyFactory.factory(compositeState);
        compositeFly1.operation("Composite Call");
        System.out.println("---------------------------------");        
        System.out.println("复合享元模式是否可以共享对象:" + (compositeFly1 == compositeFly2));
        Character state = 'a';
        Flyweight fly1 = flyFactory.factory(state);
        Flyweight fly2 = flyFactory.factory(state);
        System.out.println("单纯享元模式是否可以共享对象:" + (fly1 == fly2));
    }
}


运行结果如下:


image.png


享元模式与其他模式的联用


在享元模式的享元工厂类中通常提供一个静态的工厂方法用于返回享元对象,使用 简单工厂模式来生成享元对象;


在一个系统中,通常只有唯一一个享元工厂,因此享元工厂类可以使用单例模式进行设计;


享元模式可以结合组合模式形成复合享元模式,统一对享元对象设置外部状态。


四、享元模式的分析


享元模式是一个 考虑系统性能的设计模式,通过使用享元模式可以节约内存空间,提高系统的性能。


享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。


典型的享元工厂类代码:


public class FlyweightFactory
{
    private HashMap flyweights = new HashMap();
    public Flyweight getFlyweight(String key)
    {
        if(flyweights.containsKey(key))
        {
            return (Flyweight)flyweights.get(key);
        }
        else
        {
            Flyweight fw = new ConcreteFlyweight();
            flyweights.put(key,fw);
            return fw;
        }
    }
} 


享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。其中:


内部状态 是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享。


外部状态 是随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。


典型的享元类代码:


public class Flyweight
{
        //内部状态作为成员属性
    private String intrinsicState;
    public Flyweight(String intrinsicState)
    {
        this.intrinsicState = intrinsicState;
    }
    public void operation(String extrinsicState)
    {
        ......
    }   
}


五、享元模式在源码中的应用以及优缺点对比


享元模式在编辑器软件中大量使用,如在一个文档中多次出现相同的图片,则只需要创建一个图片对象,通过在应用程序中设置该图片出现的位置,可以实现该图片在不同地方多次重复显示。


广义上讲,在JDK类库中定义的String类也是使用享元模式的典型。

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

我们做一个测试


image.png


String类的final修饰的,以字面量的形式创建String变量时,JVM会在编译期间就把该字面量“hello”放到字符串常量池中,由java程序启动的时候就加载到内存中了。这个字符串常量池的特点就是有且只有一份相同的字面量,如果有其它相同的字面量,JVM则返回这个字面量的引用,如果没有相同的字面量,则在字符串常量池创建这个字面量并返回它的引用。
     由于s2指向的字面量"hello"在常量池中已经存在了(s1先于s2),于是JVM就返回这个字面量绑定的引用,所以s1==s2;
     s3中字面量的拼接其实就是"hello",JVM在编译期间就已经对它进行优化,所以s1和s3是相等的。
     s4中new String("lo")生成了两个对象,lo,new String("lo"),lo存在字符串常量池,lo中存在字符串常量池,new String("lo")存储在堆中,String s4 = "hel"+new String("lo")实际上是两个对象的相加,编译器不会进行优化,相加的结果存在堆中,而s1存在字符串常量池中,当然不相等。s1==s9的原理是一样的
     s4==s5两个相加的结果都在堆中,不用说,肯定不相等。
     s1==s6中,s5.intern()方法能使一个位于堆中的字符串在运行期间动态地加入到字符串常量池中(字符串常量池的内容是程序启动的时候就已经加载好了),如果字符串常量池中有该对象对饮的字面量,则返回该字面量在字符串常量池中的引用,否则,创建复制一份字面量到字符串常量池并返回它的引用。因此s1==s6输出true。


image.png

目录
相关文章
|
2天前
|
人工智能 自然语言处理 安全
阿里云AI数智鉴密:AI 生成内容如何拿到一张"防篡改的身份证"
隐形水印 + C2PA签名:让AI生成内容“持证上岗”。
1093 0
|
11天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
3656 3
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
23天前
|
人工智能 缓存 前端开发
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
DeepSeek Harness + DeepSeek V4 Pro 项目实战保姆级教程!手把手带你从零安装开源 AI 编程工具,开发架构图、知识讲解网站、3D 网页游戏、全栈 AI 应用 4 个项目,覆盖运行模式选择、插件安装与开发,看看能不能对标 Claude。
13398 93
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
|
16天前
|
Web App开发 人工智能 API
16 个超火的 DeepSeek Harness 插件,大肥鱼已经落后 N 个版本了。。。
DeepSeek Harness 精选插件推荐合集,从图片识别、浏览器操控、多 Agent 协作到手机远程控制,一口气带你看完 DSH 社区热门的十几个插件,覆盖技能扩展、UI 界面增强、整活玩法三大类,让你的鲸鱼变得更强。
1911 5
|
9天前
|
人工智能 监控 测试技术
Qwen3.8-Flash 来了,100万上下文、Agent、Coding 都加强了
8月26日,通义千问发布Qwen3.8-Flash-Next:125B参数、每Token仅激活6B,原生支持26万Token、可扩展至100万上下文;Coding、Agent与工具调用能力显著增强,面向真实软件工程任务,推动大模型从“回答问题”迈向“完成工作”。
|
12天前
|
人工智能 Linux iOS开发
Ollama使用教程:Ollama官网下载、Ollama本地部署大模型(2026最新)
Ollama 是一款免费开源的本地大模型运行工具,支持在 Windows/macOS/Linux 上离线运行 Qwen、DeepSeek、Llama 等主流开源模型,数据不出本机、隐私安全。提供 OpenAI 兼容 API,命令行一键拉取/运行/管理模型,无需联网,无调用限制,是开发者与 AI 爱好者部署本地 AI 助手的理想选择。(239 字)
|
17天前
|
人工智能 Java BI
【AI】DeepSeek Harness 安装、运行、管理插件
本文介绍了如何运行DeepSeek开源的Agent框架DeepSeek Harness(dsh)。主要内容包括:使用nvm安装适配的Node版本;通过代理加速克隆GitHub源码;使用pnpm安装依赖并启动项目;配置DeepSeek API Token;安装扩展功能的插件。该框架自带Web界面,支持模型适配、文件编辑等插件化功能
2154 1