行百里er 行百里er
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)

行百里er

Java程序员一枚
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)
  • 【设计模式】各个击破单例模式的8种写法
  • 【设计模式】策略模式之“这不就是if-else吗”
  • 【设计模式】工厂系列-FactoryMethod,AbstractFactory,Spring IOC
    • 【设计模式】只需体验三分钟,你就会跟我一样了解Facade和Mediator模式
    • 【设计模式】代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP
    • 【设计模式】通俗易懂版责任链模式
    • 【设计模式】模板模式,学会它咱也写出优雅健壮的代码!
    • 【设计模式】好玩的原型模式:Prototype
    • 【设计模式】1分钟整明白什么是Builder建造者模式
    • 设计模式
    行百里er
    2020-08-06
    目录

    【设计模式】工厂系列-FactoryMethod,AbstractFactory,Spring IOC

    作者:行百里er

    博客:https://chendapeng.cn (opens new window)

    提示

    这里是 行百里er 的博客:行百里者半九十,凡事善始善终,吾将上下而求索!

    今天来说一下设计模式的工厂系列。这一系列主要包括工厂方法、抽象工厂,最后再看看Spring的利器IOC。

    # 何为工厂

    任何可以产生对象的方法或类,都可以叫做工厂。

    so,单例模式 getInstance 也是一种工厂。

    那为什么有了new之后,还要工厂呢?

    • 灵活控制生产过程;
    • 权限、日志、管理
    • ...

    下面我就用生产防护用品来举例说明为什么要使用工厂:

    • 任意定制口罩

    继承ProtectiveEquip

    • 任意定制生产过程

    ProtectiveEquip xxxFactory.create()

    • 任意定制产品一族

    # 工厂方法

    作为有需求的客户端Client,new一个口罩出来:

    public class Client {
        public static void main(String[] args) {
            FaceMask fm = new FaceMask();
            fm.protect();
        }
    }
    
    1
    2
    3
    4
    5
    6

    定义一个口罩类:

    public class FaceMask {
        public void protect() {
            System.out.println("face masks don't let the virus enter");
        }
    }
    
    1
    2
    3
    4
    5

    如果client自我保护意识比较强,还需要定制一双防护手套,那么就需要再定义一个防护手套类HandMask,也提供一个protect方法;

    client需求又升级了,他还要防护衣服ProtectiveSuit...

    如果一直这样new下去,那就有点不太好了,要是有工厂能生产就好了。

    工厂来了:

    /**
     * 简单工厂 生产防护用品
     * 简单工厂的可扩展性不好,比如需要造新的防护用品的时候,需要加方法
     * @author 行百里者
     */
    public class SimpleProtectiveEquipFactory {
        
        FaceMask createFaceMask() {
            return new FaceMask();
        }
        
        HandMask createHandMask() {
            return new HandMask();
        }
        
        //如果还需要生产其他防护用品,就接着写createXXX方法
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    这就是简单工厂,能够生产你需要的东西,前提是你得往这个工厂里写方法。这也不太方便啊,而且不好扩展。

    那就每个工厂各司其职,自己生产自己的东西,口罩工厂生产口罩,手套工厂生产手套。。。

    口罩工厂:

    public class FaceMaskFactory {
        FaceMask create() {
            System.out.println("业务逻辑...");
            return new FaceMask();
        }
    }
    
    1
    2
    3
    4
    5
    6

    防护手套工厂:

    public class HandMaskFactory {
        HandMask create() {
            System.out.println("业务逻辑...");
            return new HandMask();
        }
    }
    
    1
    2
    3
    4
    5
    6

    等等,需要造什么,就创建什么工厂。

    客户Client这里:

    public class Client {
        public static void main(String[] args) {
            FaceMaskFactory factory = new FaceMaskFactory();
            //保护我
            factory.create().protect();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7

    由此,可以看出,工厂方法既能满足任意制定防护工具,又能任意制定生产过程——create方法由你的工厂实现。

    image.png

    那么,如果我是个大厂,想搞宇宙化战略,既能生产正常人类的防护用品,又能生产其他种族的防护用品,比如漂亮国的人,火星人等等的防护用品,我该怎么办?

    像工厂方法那样建造很多个工厂也能实现,但是有点繁琐了。。。

    image.png

    # 抽象工厂

    如何解决上面的宇宙化战略问题呢?建造生产产品一族的工厂,我们称之为抽象工厂。

    刚才提到的产品一族,比如HumanFactory生产防护用品是FaceMask、食物是Rice;UsaFactory生产防护用品是Rags、食物是Junk等等

    HumanFactory是正常人类一族; UsaFactory是漂亮国一族。

    他们各自生产本族的不同类别的产品。

    这时我们可以弄一个抽象工厂叫BaseFactory,它能生产食物、防护用品:

    public abstract class BaseFactory {
        abstract Food createFood();
        abstract ProtectiveEquip createProtectiveEquip();
    }
    
    1
    2
    3
    4

    具体的产品族分别实现这个抽象工厂:

    public class HumanFactory extends BaseFactory {
        @Override
        Food createFood() {
            //生产大米饭
            return new Rice();
        }
    
        @Override
        ProtectiveEquip createProtectiveEquip() {
            //生产口罩
            return new FaceMask();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class UsaFactory extends BaseFactory {
        @Override
        Food createFood() {
            //生产Junk Food
            return new Junk();
        }
    
        @Override
        ProtectiveEquip createProtectiveEquip() {
            //生产破布条
            return new Rags();
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    image.png

    一个抽象的工厂,可以生产两个抽象的产品;两个具体的工厂分别生产自己的产品。

    如此,便可实现可以定制任意产品族。

    这就是抽象工厂模式。

    抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

    image.png

    我们来看看抽象工厂的通用源代码,首先有两个互相影响的产品线(也叫做产品族),例如制造汽车的左侧门和右侧门,这两个应该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的。

    # Spring Bean工厂

    Spring IOC其实也是一种工厂---生产各种Bean的工厂,这里我们只简单说一下它的用法。

    pom.xml引入Spring的包

    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    在Spring配置文件app.xml中定义想要被Spring托管的类:

    <bean id="rice" class="com.traveler100.dp.abstractfactory.Rice"></bean>
    
    1

    Client可直接使用:

    ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml");
    Rice rice = (Rice) ctx.getBean("rice");
    rice.printName();
    
    1
    2
    3

    牛逼不?省去了很多代码吧,什么xxxFactory啊,什么继承啊等等,都不用我们自己去写了,我们可以把很多类直接扔给Spring,让它帮我们实例化,把Bean的控制权交给Spring,这就是所谓的控制反转,Spring IOC

    我们可以把它看成造各种Bean的工厂,也就是Spring Bean工厂。


    首发公众号 行百里er ,欢迎老铁们关注阅读指正。

    首发公众号 行百里er ,欢迎老铁们关注阅读指正。代码仓库 GitHub github.com/ChenDapengJava (opens new window)

    #设计模式
    上次更新: 2022/10/06, 17:45:29
    【设计模式】策略模式之“这不就是if-else吗”
    【设计模式】只需体验三分钟,你就会跟我一样了解Facade和Mediator模式

    ← 【设计模式】策略模式之“这不就是if-else吗” 【设计模式】只需体验三分钟,你就会跟我一样了解Facade和Mediator模式→

    最近更新
    01
    重要数据不能丢!MySQL数据库定期备份保驾护航!
    05-22
    02
    分布式事务解决方案之 Seata(二):Seata AT 模式
    09-09
    03
    Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
    09-05
    更多文章>
    Theme by Vdoing | Copyright © 2020-2023 行百里er | MIT License | 豫ICP备2022020385号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式