【设计模式】工厂系列-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();
}
}
2
3
4
5
6
定义一个口罩类:
public class FaceMask {
public void protect() {
System.out.println("face masks don't let the virus enter");
}
}
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方法
}
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();
}
}
2
3
4
5
6
防护手套工厂:
public class HandMaskFactory {
HandMask create() {
System.out.println("业务逻辑...");
return new HandMask();
}
}
2
3
4
5
6
等等,需要造什么,就创建什么工厂。
客户Client
这里:
public class Client {
public static void main(String[] args) {
FaceMaskFactory factory = new FaceMaskFactory();
//保护我
factory.create().protect();
}
}
2
3
4
5
6
7
由此,可以看出,工厂方法既能满足任意制定防护工具
,又能任意制定生产过程
——create
方法由你的工厂实现。
那么,如果我是个大厂,想搞宇宙化战略,既能生产正常人类
的防护用品,又能生产其他种族的防护用品,比如漂亮国
的人,火星人
等等的防护用品,我该怎么办?
像工厂方法那样建造很多个工厂也能实现,但是有点繁琐了。。。
# 抽象工厂
如何解决上面的
宇宙化战略
问题呢?建造生产产品一族的工厂,我们称之为抽象工厂
。
刚才提到的产品一族
,比如HumanFactory
生产防护用品是FaceMask
、食物是Rice
;UsaFactory
生产防护用品是Rags
、食物是Junk
等等
HumanFactory
是正常人类一族;
UsaFactory
是漂亮国
一族。
他们各自生产本族的不同类别的产品。
这时我们可以弄一个抽象工厂叫BaseFactory
,它能生产食物、防护用品:
public abstract class BaseFactory {
abstract Food createFood();
abstract ProtectiveEquip createProtectiveEquip();
}
2
3
4
具体的产品族分别实现这个抽象工厂:
public class HumanFactory extends BaseFactory {
@Override
Food createFood() {
//生产大米饭
return new Rice();
}
@Override
ProtectiveEquip createProtectiveEquip() {
//生产口罩
return new FaceMask();
}
}
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();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
一个抽象的工厂,可以生产两个抽象的产品;两个具体的工厂分别生产自己的产品。
如此,便可实现可以定制任意产品族
。
这就是抽象工厂模式
。
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
我们来看看抽象工厂的通用源代码,首先有两个互相影响的产品线(也叫做产品族),例如制造汽车的左侧门和右侧门,这两个应该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的。
# 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>
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>
Client
可直接使用:
ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml");
Rice rice = (Rice) ctx.getBean("rice");
rice.printName();
2
3
牛逼不?省去了很多代码吧,什么xxxFactory啊,什么继承啊等等,都不用我们自己去写了,我们可以把很多类直接扔给Spring,让它帮我们实例化,把Bean
的控制权交给Spring
,这就是所谓的控制反转
,Spring IOC
我们可以把它看成造各种Bean
的工厂,也就是Spring Bean工厂
。
首发公众号 行百里er ,欢迎老铁们关注阅读指正。
首发公众号 行百里er ,欢迎老铁们关注阅读指正。代码仓库 GitHub github.com/ChenDapengJava (opens new window)