【Java教程】Day20-11 设计模式:结构型模式——享元模式(Flyweight)

1. 享元模式概述

享元模式(Flyweight Pattern)是一种结构型设计模式,它的核心思想是通过共享对象来减少内存占用,特别适用于需要大量相似对象的场景。享元模式的基本原理是:如果一个对象实例的状态不可变,则多次创建相同实例没有必要,可以直接返回共享的对象实例。这样不仅能够节省内存,还能提高系统的性能,避免频繁地创建和销毁对象。

享元模式主要通过工厂方法来管理共享实例,通过在工厂方法内部实现对象缓存,从而实现对象复用。对于不可变对象,享元模式尤其有效,因为这些对象的状态一旦创建就不会改变。

2. 享元模式的适用场景

享元模式适用于以下情况:

  • 系统中存在大量相似对象,且这些对象的状态不可变。

  • 创建对象的代价较大,频繁创建相同对象导致内存和性能浪费。

  • 对象的某些属性可以共享,而其他属性则是特有的。

3. 享元模式的实现

3.1 Java标准库中的应用

在Java中,享元模式的一个经典应用是包装类型(如 ByteInteger)的实现。例如,Integer 类的 valueOf() 方法使用了享元模式。当传入的整数值在 -128 到 127 之间时,valueOf() 方法返回的是一个共享的缓存实例,而不是每次创建新的 Integer 对象。

下面是一个简单的示例:

javapublic class Main {    public static void main(String[] args) {        Integer n1 = Integer.valueOf(100);        Integer n2 = Integer.valueOf(100);        System.out.println(n1 == n2); // true    }}

 

在这个例子中,n1 和 n2 实际上指向的是同一个 Integer 实例,而不是两个不同的对象。这是享元模式的典型实现,缓存了对象,避免了不必要的创建。

3.2 享元模式的手动实现

我们可以通过静态工厂方法来实现享元模式。在工厂方法中,首先检查对象是否存在于缓存中,如果存在,则返回缓存对象;如果不存在,则创建一个新的对象并将其缓存。

下面是一个 Student 类的例子,展示了如何使用享元模式来管理对象的缓存:

javaimport java.util.HashMap;import java.util.Map;public class Student {    // 持有缓存    private static final Map<String, Student> cache = new HashMap<>();    // 静态工厂方法    public static Student create(int id, String name) {        String key = id + "\n" + name;        // 先查找缓存        Student std = cache.get(key);        if (std == null) {            // 未找到, 创建新对象            System.out.println(String.format("create new Student(%s, %s)", id, name));            std = new Student(id, name);            // 放入缓存            cache.put(key, std);        } else {            // 缓存中存在            System.out.println(String.format("return cached Student(%s, %s)", std.id, std.name));        }        return std;    }    private final int id;    private final String name;    public Student(int id, String name) {        this.id = id;        this.name = name;    }}

 

在这个例子中,Student 类通过静态工厂方法 create() 来管理对象的缓存。每次创建 Student 对象时,首先检查缓存中是否已有相同的对象。如果缓存中没有,才创建一个新的 Student 对象,并将其放入缓存。

3.3 客户端调用

客户端可以使用 create() 方法来创建或获取 Student 对象:

javapublic class Client {    public static void main(String[] args) {        Student student1 = Student.create(1, "Alice");        Student student2 = Student.create(1, "Alice");        Student student3 = Student.create(2, "Bob");        // 输出:        // create new Student(1, Alice)        // return cached Student(1, Alice)        // create new Student(2, Bob)    }}

 

在这个例子中,student1 和 student2 具有相同的 id 和 name,因此第二次调用 create() 方法时,返回的是缓存中的对象,而不是创建一个新的对象。这样有效地节省了内存和计算资源。

4. 享元模式在实际开发中的应用

4.1 缓存实现

享元模式常常用于缓存管理,特别是在需要频繁请求相同数据的场景中。如果每次都从数据库或文件系统中加载相同的对象,不仅浪费了时间和计算资源,而且增加了数据库的负担。通过缓存机制,可以直接从内存中获取对象,从而提高性能。

例如,许多大型应用都会使用缓存库(如 Guava Cache 或 Redis)来实现对象缓存,以减少数据库查询的次数。缓存对象通常是不可变的,可以使用享元模式来有效管理缓存,避免重复创建。

4.2 字符串池

Java中的 String 类型也使用了享元模式。对于常量字符串(即字面量字符串),Java会将其保存在字符串池中。当再次创建相同的字符串时,Java会直接返回池中的实例,而不是创建新的对象。这样有效减少了内存消耗,提升了性能。

javapublic class StringPoolExample {    public static void main(String[] args) {        String s1 = "hello";        String s2 = "hello";        System.out.println(s1 == s2); // true    }}

 

5. 练习

请使用享元模式实现一个简单的缓存系统。该系统缓存的是用户信息,使用 id 和 name 作为缓存的关键字。要求实现一个 User 类,通过静态工厂方法 create() 来管理用户对象的缓存,并保证同样的用户信息不会被重复创建。

下载练习:[下载链接]

6. 小结

享元模式通过共享技术有效减少了对象的创建和内存占用,尤其适用于需要频繁创建相似对象的场景。它的核心思想是通过缓存已创建的对象来避免重复创建,提高系统的性能。享元模式的应用场景非常广泛,包括字符串池、缓存管理等。

通过享元模式,我们能够优化内存使用,减少对象创建带来的性能开销。在实际开发中,使用工厂方法来创建和管理对象是实现享元模式的一种常见方式,可以有效提升系统的性能和可维护性。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值