关于spring-cloud:跟二师兄学Nacos吧EXT01篇-看看Nacos是怎么活学活用简单工厂模式的

32次阅读

共计 4261 个字符,预计需要花费 11 分钟才能阅读完成。

学习不必那么功利,二师兄带你一起轻松读源码~

番外篇简介

Nacos 源码剖析系列文章,在开篇曾经提到过,写作的指标有两个:第一,可能零碎的学习 Nacos 常识;第二,可能基于 Nacos 学到波及到的知识点或面。

为了不便大家学习,绝对应的文章题目会有所区别,Nacos 原理局部命名依照失常编号进行。而番外篇,也就是技术点的解说则会在文章编号上增加“EXT-”的前缀。这样,如果大家只想学习 Nacos 原理常识,则可跳过 EXT 前缀的文章。

这篇文章咱们来看看 Nacos Client 中对工厂模式的应用。这里分两个步骤来理解,首先看看规范的工厂模式是什么样子的,而后再比照一下 Nacos 中的实现与规范实现有什么区别。

工厂模式概述

在 23 种设计模式当中,工厂模式蕴含两种:工厂办法模式和形象工厂模式。它们都属于创立型模式,而还有一种简略工厂模式,尽管常常被用到,但可能是过于简略,未被纳入 23 种设计模式当中。

简略工厂模式

上面先介绍一下,简略工厂模式,并对 Nacos 中的应用进行比照,并思考为什么会这样设计。

简略工厂模式简介

简略工厂模式,又叫做动态工厂办法(Static Factory Method)模式。简略工厂模式是由一个工厂对象依据不同的参数类型返回不同实例。简略工厂模式是工厂模式家族中最简略实用的模式,能够了解为是不同工厂模式的一个非凡实现。

对于简略工厂模式,要解决的问题便是封装实例创立的过程。须要什么类,只需传入一个对应的参数,就能够取得所需的对象,调用者无需晓得实例的创立过程。被创立的实例通常都具备独特的父类。

简略工厂模式的构造

UML 图展现如下:

简略工厂通常包含三局部:

  • Factory(工厂):外围局部,负责实现创立所有产品的外部逻辑,工厂类能够被外界间接调用,创立所需对象;
  • AbstractProduct(形象产品类):工厂类所创立的所有对象的父类,封装了产品对象的公共办法,所有的具体产品为其子类对象;
  • ConcreteProduct(具体产品):简略工厂模式的创立指标,实现了形象产品类,所有被创立的对象都是某个具体类的实例;

其中形象产品类能够是接口,也能够说抽象类。

简略工厂模式的实现

这里假如 Nacos 的配置核心服务和命名服务都继承自对立的 NacosService,同时都须要提供一个注册办法。

形象产品类定义如下:

public interface NacosService {
   /**
    * 注册实例信息
    * @param object 实例信息,这里用 Object 代替
    */
   void register(Object object);
}

命名服务 NamingService 的具体实现:

public class NamingService implements NacosService {

   @Override
   public void register(Object object) {System.out.println("注册命名服务胜利");
   }
}

配置服务 ConfigService 的具体实现:

public class ConfigService implements NacosService {

   @Override
   public void register(Object object) {System.out.println("配置核心实例注册胜利");
   }
}

提供一个工厂类 NacosFactory:

public class NacosFactory {public static NacosService getService(String name) {if ("naming".equals(name)) {return new NamingService();
      } else {return new ConfigService();
      }
   }
}

其中依据传入的参数,生成不同类型的 NacosService 具体实现。

此时,客户端就能够间接调用该工厂:

public class Client {public static void main(String[] args) {NacosService nacosService = NacosFactory.getService("naming");
      nacosService.register(new Object());
   }
}

能够看出,此时客户端并不需要关注 NacosService 的具体实现类是如何被创立的,只须要通过 NacosFactory 来创立即可。这样,就把比较复杂的创立过程封装在了工厂类中。

简略工厂模式的优缺点

简略工厂模式的长处:

  • 工厂类可蕴含必要的逻辑判断,可决定不同参数创立不同产品的实例。实现了创立职责的拆散;
  • 客户端无需晓得所创立具体产品的类名,只需晓得参数即可;
  • 通过引入配置文件,能够在不批改任何客户端代码的状况下更换和减少新的具体产品类,在肯定水平上进步了零碎的灵活性;

简略工厂模式的毛病:

  • 工厂类集成了产品创立逻辑,职责过重;
  • 减少零碎中类的个数,减少零碎复杂度和了解难度;
  • 违反了设计模式中的开闭准则,新增产品需批改工厂逻辑;
  • 简略工厂模式因为应用了动态工厂办法,造成工厂角色无奈造成基于继承的等级构造。

Nacos Client 的简略工厂模式

在 Nacos 的 client 中,提供了一个 NacosFactory 的工厂类,该类对立提供了创立 ConfigService(配置核心服务)、NamingService(注册核心服务)和 NamingMaintainService(注册核心实例操作服务)的实例化办法。

在源码中能够看到是通过如下形式创立 NamingService 的:

NamingService namingService = NacosFactory.createNamingService(properties);

NacosFactory 的局部源码:

public class NacosFactory {public static ConfigService createConfigService(Properties properties) throws NacosException {return ConfigFactory.createConfigService(properties);
    }
    
    public static NamingService createNamingService(Properties properties) throws NacosException {return NamingFactory.createNamingService(properties);
    }
    
    // ... 省略其余办法
}

乍一看该类的名字,你可能曾经意识到它是工厂模式中的一种。但认真比照会发现,哪一种如同都不是。

首先,咱们来看最终创立进去的 NamingService 和 ConfigService,它们各自独立,并不属于同一个形象产品类。那这样创立进去也叫简略工厂模式吗?

这里要留神后面定义简略工厂模式时说过“被创立的实例通常都具备独特的父类”,这里的“通常”也就是说大多数状况下是这样的,也容许不实现自同一个接口或抽象类。

其次,咱们会发现,NacosFactory 中也没有依据办法参数进行不同的对象进行创立,而是间接提供了多个办法来创立不同的对象实例。这又是为什么呢?

这样设计可能出于三个目标:

第一,无论 NamingService 还是 ConfigService,它们自身曾经对应的工厂类 ConfigFactory 和 NamingFactory 了,如果须要独自创立其实是能够间接调用对应的工厂类的;

第二,NacosFactory 存在的目标,自身就是为了达到“聚合”的作用,也就是把所有 Nacos 相干的服务实例集中对外提供,比方 Spring Cloud 集成时应用的 NacosFactory 来创立 NamingService,而不是通过 NamingFactory 来创立。

第三,业务创立比较简单。也就是对于 Nacos 来说,目前版本中只会提供这三个 Service,而不会再多进去其余的,因而开闭准则也就没那么重要了。于是就进行了简化解决。

因而,在应用工厂模式时并不一定非要按规范定义,教条式的进行实现,依据具体的场景能够灵活运用。基本上所有的设计模式都有相似的特点。

Nacos API 的简略工厂模式

下面看到的是 Nacos Client 我的项目中的简略工厂模式实现,再进一步,咱们看看该工厂模式中嵌套的 NamingFactory:

public class NamingFactory {public static NamingService createNamingService(Properties properties) throws NacosException {
        try {Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
            Constructor constructor = driverImplClass.getConstructor(Properties.class);
            return (NamingService) constructor.newInstance(properties);
        } catch (Throwable e) {throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
        }
    }
    // ...
}

在 NamingFactory 中的实现,才更靠近规范的简略工厂模式。因为它提供的 createNamingService 办法,返回的是形象产品类 NamingService(接口)。而在该办法外部呢,才真正创立了它的实现类,尽管实现类只有一个。

小结

学习本文其实想给大家传递两个观点:第一,浏览源码时,其实咱们能够多思考一步,比方看看它用到了什么设计模式或知识点;第二,学习设计模式时肯定要活学活用,实在的实际环境变动齐全,没必要刻板的依照概念来。活学活用,灵便变动,才达到了学习的最高境界。

源码地址:https://github.com/secbr/naco…

如果文章内容有问题或想技术探讨请分割我(微信:zhuan2quan,备注 Nacos),如果感觉写的还不错,值得一起学习,那就关注一下吧。

博主简介:《SpringBoot 技术底细》技术图书作者,热爱钻研技术,写技术干货文章。

公众号:「程序新视界」,博主的公众号,欢送关注~

技术交换:请分割博主微信号:zhuan2quan

正文完
 0