设计模式——多例模式(23种之外)

多例模式(Multiton Pattern)是一种特殊的设计模式,它属于创建型模式。与单例模式(Singleton Pattern)相比,多例模式允许一个类有多个实例,但是实例的数量是有限制的,并且这些实例在全局范围内是共享的。这种模式适用于当系统中有且仅有几个对象实例被频繁使用,且这些对象的创建和销毁开销较大时。

在我的SpringBoot项目中遇到的一个问题,最后使用多例模式解决了。问题是我需要通过传入参数实例化一个对象,希望如果出入的参数相同那么得到的实例应该是一样的,如果参数不同则实例化的参数是不同的。这个问题我一开始想到了单例模式和工厂模式结合来解决,在工厂中判断参数是否已经存在从而创建单例实例,后面越想越觉得自己搞复杂了,虽然可以解决这个问题,最后果然发现还有一种多例模式可以完美解决这个问题。那么,下面就开始演示如何使用多例模式:

需要实例化的User类

public class User {
    String id;

    public User(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                '}';
    }
}

直接获取对象的缺点

我们正常的实例化其实是不满足条件的,例如如下代码:

public class MainTest {
    public static void main(String[] args) { 
        User user1 = new User("123");
        User user2 = new User("123");
        
        System.out.println(user1.hashCode());
        System.out.println(user2.hashCode());

        System.out.println(user1 == user2);
    }
}

输出结果

128893786
1732398722
false

显然,这样new出来的两个对象不是同一个,但是在这种情况下,我们希望通过参数构造的对象只要参数相同就能拿到同一个对象,类似单例模式,而不同参数则创建新的对象。这种情况就非常适合多例模式,下面介绍多例模式解决这个问题。

多例模式

多例模式的特点

  • 实例数量有限:与单例模式不同,多例模式允许创建多个实例,但实例的数量是有限的。
  • 全局访问:所有实例都是全局可访问的,通常通过一个全局的访问点来获取实例。
  • 实例唯一性:在允许的范围内,每个实例都是唯一的。

下面是线程安全的实现,这里我们使用一个工厂类来管理我们的User,只要是相同的id就一定能够获得相同的User,不同的id拿到的User不同。代码如下:

public class UserMultitonFactory {
    private static final ConcurrentHashMap<String, User> userMap = new ConcurrentHashMap<>();

    private UserMultitonFactory(){} // 私有构造方法防止new实例化

    public static User getInstance(String id) {
        // 使用computeIfAbsent方法确保线程安全的实例创建
        return userMap.computeIfAbsent(id,k -> new User(k)); // 这个k就是id
    }

    public static void destroyInstance(String id){
        userMap.remove(id);
    }
}

测试

public class MainTest {
    public static void main(String[] args) {
        User user1 = UserMultitonFactory.getInstance("123");
        User user2 = UserMultitonFactory.getInstance("123");
        User user3 = UserMultitonFactory.getInstance("001");

        System.out.println(user1.hashCode());
        System.out.println(user2.hashCode());
        System.out.println(user3.hashCode());
    }
}

结果

1108411398
1108411398
1394438858

这里我们是使用一个工厂类来管理User的创建,当然也可以让User自己成为一个多例模式类,代码如下:


public class UserMultiton {
    String id;

    private static final ConcurrentHashMap<String, UserMultiton> userMap = new ConcurrentHashMap<>();

    private UserMultiton(String id) { // 禁止外部创建该类
        this.id = id;
    }

    public static UserMultiton getInstance(String id){
        // 使用computeIfAbsent方法确保线程安全的实例创建
        return userMap.computeIfAbsent(id,k -> new UserMultiton(k)); // 这个k就是id
    }

    public static void destroyInstance(String id){
        userMap.remove(id);
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                '}';
    }
}

应用场景

多例模式是一种创建型设计模式,其应用场景主要在于管理可重复使用的资源,如线程池、数据库连接池等。这些场景中,多例模式能够复用已有实例,避免重复创建对象,从而提高系统性能并避免浪费系统资源。

缺点

多例模式的缺点包括:

  • 难以扩展:多例模式的实例数量是固定的,难以动态地增加或减少实例数量。
  • 难以测试:由于多例模式的实例数量是固定的,难以对每个实例进行单独的测试。
  • 破坏封装性:多例模式需要全局访问实例,这破坏了封装性,使得代码难以维护和扩展。
  • 代码复杂度高:多例模式的实现需要考虑线程安全、序列化等问题,因此代码复杂度较高。

相关推荐

  1. 设计模式——模式23之外

    2024-07-13 16:50:04       25 阅读
  2. 设计模式——23

    2024-07-13 16:50:04       50 阅读
  3. 23设计模式

    2024-07-13 16:50:04       33 阅读
  4. 23设计模式

    2024-07-13 16:50:04       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 16:50:04       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 16:50:04       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 16:50:04       62 阅读
  4. Python语言-面向对象

    2024-07-13 16:50:04       72 阅读

热门阅读

  1. Redis 中的跳跃表(Skiplist)基本介绍

    2024-07-13 16:50:04       22 阅读
  2. python的面向对象编程

    2024-07-13 16:50:04       22 阅读
  3. 单元测试有什么好处呢?

    2024-07-13 16:50:04       22 阅读
  4. Git使用介绍教程

    2024-07-13 16:50:04       20 阅读
  5. Python 使用总结之 docx 添加图片设置图片大小详解

    2024-07-13 16:50:04       24 阅读
  6. unity 学习笔记 UI

    2024-07-13 16:50:04       22 阅读
  7. py每日spider案例之tts制作接口

    2024-07-13 16:50:04       18 阅读
  8. 创建型模式-单例模式

    2024-07-13 16:50:04       19 阅读
  9. 云WAF在电子商务领域具体能提供哪些安全功能?

    2024-07-13 16:50:04       21 阅读