《跟二师兄学Nacos吧》EXT-02篇 面试官问工厂模式,你理解的对吗?

简介: 《跟二师兄学Nacos吧》EXT-02篇 面试官问工厂模式,你理解的对吗?

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

在上篇文章中,我们学习了Nacos中是如何灵活运用《简单工厂模式》的。而设计模式在面试过程中也经常会出现。当面试官问到:说说工厂模式是如何实现的?他问的工厂模式指的是什么?

这篇文章属于扩展篇的扩展,我们基于简单工厂模式,再来聊聊工厂模式。

工厂方法模式

先来回答上面的问题,如果笼统的讲工厂模式,通常包括:简单工厂/静态工厂、工厂方法模式和抽象工厂模式。上节讲了简单工厂模式,而抽象工厂模式一般应用在比较复杂的大型应用中,也不太常见。

因此,如果工厂模式只是指某一个模式的话,那么说的就是工厂方法模式。

工厂方法模式简介

工厂方法模式(Factory Method Pattern)又称工厂模式、多态工厂模式和虚拟构造器模式。

在讲简单工厂模式时,已经知道该模式存在一些缺点,比如工厂类业务逻辑过于复杂,违背了开闭原则和高内聚低耦合的原则。同时,还由于方法是静态的,还无法形成继承的层级结构。

那么,我们是否可以将工厂类进行抽象,提供一个公共的接口,而工厂类的子类负责创建具体的产品对象,这样不就达到了解耦的目标了吗?

因此,在工厂方法模式中,工厂父类定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,通过工厂子类来确定究竟应该实例化哪一个具体的产品类。

工厂方法模式结构图

在看工厂方法模式的结构图之前,先来回顾一下简单工厂模式的结构图:image.png我们对此结构图进行扩展,将Factory这个工厂类进行抽象化处理,于是就得到工厂方法模式:

image.png上图中被虚线框起来的部分便是变化的部分,第一个变化是工厂类被抽象化了,提供了一个抽象的AbstractFactory。既然抽象了,必定会有具体的工厂实现类,这个实现类与产品相对照。这样,便达到了修改一个产品的创建逻辑,并不会影响到其他产品的创建,达到了解耦的效果。

下面再梳理一下工厂方法模式的核心角色:

  • 抽象产品(Product):产品的抽象类或接口,负责定义产品的特征和共性。
  • 具体产品(Concrete Product):具体的产品类。
  • 抽象工厂(AbstractFactory):产品的创建类,工厂接口。
  • 具体工厂(ConcreteFactory):具体的创建类,工厂实现。

工厂方法模式实现

这里的实例我们还以Nacos的配置服务和命名服务为例。假设配置服务和命名服务都集成自同一个NacosService,同时呢,它们的创建又通过不同的子工厂进行创建。

定义抽象产品类及其实现类:

// 抽象产品类
public interface NacosService {
   /**
    * 注册实例信息
    * @param object 实例信息,这里用Object代替
    */
   void register(Object object);
}
// 配置中心服务实现
public class ConfigService implements NacosService {
   @Override
   public void register(Object object) {
      System.out.println("配置中心实例注册成功");
   }
}
// 命名服务注册实现
public class NamingService implements NacosService {
   @Override
   public void register(Object object) {
      System.out.println("注册命名服务成功");
   }
}

定义抽象工厂类及其实现类:

// 抽象工厂类,定义统一的方法
public interface NacosFactory {
    NacosService getService();
}
// 配置服务的工厂类实现
public class ConfigNacosFactory implements NacosFactory {
    @Override
    public NacosService getService() {
        return new ConfigService();
    }
}
// 命名服务的工厂类实现
public class NamingNacosFactory implements NacosFactory {
    @Override
    public NacosService getService() {
        return new NamingService();
    }
}

客户端实现:

public class Client {
    public static void main(String[] args) {
        // 配置中心
        ConfigNacosFactory configNacosFactory = new ConfigNacosFactory();
        NacosService configService = configNacosFactory.getService();
        configService.register(new Object());
        // 注册中心
        NamingNacosFactory namingNacosFactory = new NamingNacosFactory();
        NacosService namingService = namingNacosFactory.getService();
        namingService.register(new Object());
    }
}

客户端可根据需要,创建不同的工程子类,然后通过具体的工厂子类实现具体的产品创建。关于工厂方法模式的实现,建议对照参考简单工厂模式,这样更方便理解和学习。

工厂方法模式的优缺点

工厂方法模式对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

优点:

  • 客户端只需知道具体工厂就可得到所要的产品,无须知道产品的具体创建过程;
  • 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类;
  • 符合开闭原则、符合单一职责原则、解决类简单工厂模式无法继承等级结构问题。

缺点:

  • 类数量增多,新增新产品时还需要新增对应的工厂实现类;
  • 增加了系统的抽象性和理解难度;
  • 抽象产品只能生产一种产品,如果换一个产品的话,还是需要修改产品类的。此弊端可使用抽象工厂模式解决。

工厂方法模式的应用场景

应用场景:

  • 客户只知道创建产品的工厂名,而不知道具体的产品名;
  • 创建对象的任务由多个具体工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
  • 客户不关心创建产品的细节,只关心产品的品牌;

小结

就工厂模式本身而言并不难,但我们在学习设计模式时最头痛的事就是学完就忘。如果像本文这样,深刻理解了设计模式设计的初衷、使用场景以及进化历程,便更有利于记忆。本文的重点便是进行这方面思维的引导,你学到了吗?

目录
相关文章
|
设计模式
【面试题精讲】javaIO设计模式之工厂模式
【面试题精讲】javaIO设计模式之工厂模式
|
4月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
78 1
|
4月前
|
设计模式 缓存 安全
Java面试题:工厂模式与内存泄漏防范?线程安全与volatile关键字的适用性?并发集合与线程池管理问题
Java面试题:工厂模式与内存泄漏防范?线程安全与volatile关键字的适用性?并发集合与线程池管理问题
57 1
|
4月前
|
设计模式 Java 数据库连接
Java面试题:简述工厂模式的种类及其应用场景,你能举个例子吗?
Java面试题:简述工厂模式的种类及其应用场景,你能举个例子吗?
34 0
|
Java 测试技术 API
线程池,以及线程池的实现以及面试常问的问题,工厂模式,常见的锁策略(面试常考,要了解,不行就背)
线程池,以及线程池的实现以及面试常问的问题,工厂模式,常见的锁策略(面试常考,要了解,不行就背)
|
设计模式
面试最常见的设计模式之工厂模式
面试最常见的设计模式之工厂模式
117 1
阿里面试官:使用策略模式+工厂模式干掉代码中过多的if-else
过多if-else项目背景 如果一开始就知道现在的业务需要,大部分人都不会在代码里添加过多的if-else判断的,烂代码基本都是刚开始写代码时并没有太多的需求,随着期需求不断的修改增加,开发时间也较的紧张,代码往往都是怎么快速怎么写。当然多写一个if-else比使用各种设计模式肯定来的更快速了,这也就导致项目代码慢慢变得臃肿,难以维护的主要原因。在有空闲时间的情况下就可以给以前的代码做一次手术了。先看本次未优化前的代码:
|
存储 运维 Java
《跟二师兄学Nacos》02篇 Nacos的临时与持久化实例,傻傻分不清?
《跟二师兄学Nacos》02篇 Nacos的临时与持久化实例,傻傻分不清?
509 1
|
设计模式 缓存 Java
《跟二师兄学Nacos吧》EXT-04篇 Nacos竟然是这样使用代理模式的?
《跟二师兄学Nacos吧》EXT-04篇 Nacos竟然是这样使用代理模式的?
221 0
《跟二师兄学Nacos吧》EXT-04篇 Nacos竟然是这样使用代理模式的?
|
Java API Nacos
《跟二师兄学Nacos吧》EXT-03篇 Nacos中此处为什么采用反射机制?
《跟二师兄学Nacos吧》EXT-03篇 Nacos中此处为什么采用反射机制?
133 0
《跟二师兄学Nacos吧》EXT-03篇 Nacos中此处为什么采用反射机制?