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

番外篇简介

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