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

2024-07-14 1888阅读

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

设计模式——多例模式(23种之外)
(图片来源网络,侵删)

在我的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 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 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 + '\'' +
                    '}';
        }
    }
    

    应用场景

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

    缺点

    多例模式的缺点包括:

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

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]