多例模式(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 + '\'' +
- '}';
- }
- }
复制代码 应用场景
多例模式是一种创建型设计模式,其应用场景重要在于管理可重复利用的资源,如线程池、数据库连接池等。这些场景中,多例模式可以或许复用已有实例,克制重复创建对象,从而进步系统性能并克制浪费系统资源。
缺点
多例模式的缺点包括:
- 难以扩展:多例模式的实例数目是固定的,难以动态地增长或淘汰实例数目。
- 难以测试:由于多例模式的实例数目是固定的,难以对每个实例举行单独的测试。
- 破坏封装性:多例模式需要全局访问实例,这破坏了封装性,使得代码难以维护和扩展。
- 代码复杂度高:多例模式的实现需要考虑线程安全、序列化等题目,因此代码复杂度较高。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |