# 《Java极简设计模式》第02章:抽象工厂模式(AbstractFactoty)
沉淀,成长,突破,帮助他人,成就自我。
- 本章难度:★★☆☆☆
- 本章重点:用最简短的篇幅介绍抽象工厂模式最核心的知识,理解抽象工厂模式的设计精髓,并能够灵活运用到实际项目中,编写可维护的代码。
# 一、概述
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
抽象⼯⼚也可以称作其他⼯⼚的⼯⼚,它可以在抽象⼯⼚中创建出其他⼯⼚,与⼯⼚模式⼀样,都是⽤来解决接⼝选择的问题,同样都属于创建型模式
# 二、为何使用
工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。
为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
# 三、实用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
# 四、参与者
- AbstractFactory 声明一个创建抽象产品对象的操作接口。
- ConcreteFactory 实现创建具体产品对象的操作。
- AbstractProduct 为一类产品对象声明一个接口。
- ConcreteProduct 定义一个将被相应的具体工厂创建的产品对象。 实现AbstractProduct接口。
- Client 仅使用由AbstractFactory和AbstractProduct类声明的接口
# 五、类图
# 六、示例一
- AbstractFactory
定义抽象工程类IAnimalFactory
public interface IAnimalFactory {
/**
* 定义创建Icat接口实例的方法
* @return
*/
ICat createCat();
/**
* 定义创建IDog接口实例的方法
* @return
*/
IDog createDog();
}
2
3
4
5
6
7
8
9
10
11
12
- ConcreteFactory
创建抽象工厂类的两个实现类,WhiteAnimalFactory和BlackAnimalFactory
public class WhiteAnimalFactory implements IAnimalFactory {
public ICat createCat() {
return new WhiteCat();
}
public IDog createDog() {
return new WhiteDog();
}
}
2
3
4
5
6
7
8
9
10
public class BlackAnimalFactory implements IAnimalFactory {
@Override
public ICat createCat() {
return new BlackCat();
}
public IDog createDog() {
return new BlackDog();
}
}
2
3
4
5
6
7
8
9
10
11
- AbstractProduct
定义抽象工厂中要生产的抽象产品接口ICat和IDog
public interface ICat {
/**
* 定义方法
*/
void eat();
}
2
3
4
5
6
public interface IDog {
/**
* 定义方法
*/
void eat();
}
2
3
4
5
6
- ConcreteProduct
创建产品的实现类BlackCat、BlackDog、WhiteCat、WhiteDog
public class BlackCat implements ICat {
@Override
public void eat() {
System.out.println("The black cat is eating!");
}
}
2
3
4
5
6
public class BlackDog implements IDog {
@Override
public void eat() {
System.out.println("The black dog is eating");
}
}
2
3
4
5
6
public class WhiteCat implements ICat {
@Override
public void eat() {
System.out.println("The white cat is eating!");
}
}
2
3
4
5
6
public class WhiteDog implements IDog {
@Override
public void eat() {
System.out.println("The white dog is eating!");
}
}
2
3
4
5
6
7
- Client
定义一个测试类Test
public class Test {
public static void main(String[] args) {
IAnimalFactory blackAnimalFactory = new BlackAnimalFactory();
ICat blackCat = blackAnimalFactory.createCat();
blackCat.eat();
IDog blackDog = blackAnimalFactory.createDog();
blackDog.eat();
IAnimalFactory whiteAnimalFactory = new WhiteAnimalFactory();
ICat whiteCat = whiteAnimalFactory.createCat();
whiteCat.eat();
IDog whiteDog = whiteAnimalFactory.createDog();
whiteDog.eat();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 输出结果
The black cat is eating!
The black dog is eating
The white cat is eating!
The white dog is eating!
2
3
4
# 七、示例二
公司早期接⼊七⽜云OSS(对象存储服务)上传图⽚与视频,后因业务调整,公司要求额外⽀持阿⾥云、腾讯云等其他云服务商,并且可以对客户提供外界访问。
设计要求为:允许在不破坏原有代码逻辑情况下,实现对任意三⽅云⼚商的接⼊。

抽象⼯⼚模式
顾名思义即为⼯⼚的⼯⼚,通过构建顶层的抽象⼯⼚和抽象的产品,屏蔽系列产品的构建过程。
抽象⼯⼚与抽象的系列产品接⼝
package com.itlaoqi.abstractfactory.factory;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
public interface AbstractOssFactory {
public OssImage uploadImage(byte[] bytes);
public OssVideo uploadVideo(byte[] bytes);
}
package com.itlaoqi.abstractfactory.factory.product;
public interface OssImage {
public String getThumb() ;
public String getWatermark() ;
public String getEnhance();
}
package com.itlaoqi.abstractfactory.factory.product;
public interface OssVideo {
public String get720P();
public String get1080P();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 七⽜云实现
⼯⼚实现类
package com.itlaoqi.abstractfactory.qiniu;
import com.itlaoqi.abstractfactory.factory.AbstractOssFactory;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
import com.itlaoqi.abstractfactory.qiniu.product.QiniuOssImage;
import com.itlaoqi.abstractfactory.qiniu.product.QiniuOssVideo;
public class QiniuOssFactory implements AbstractOssFactory {
@Override
public OssImage uploadImage(byte[] bytes) {
return new QiniuOssImage(bytes,"IT⽼⻬");
}
@Override
public OssVideo uploadVideo(byte[] bytes) {
return new QiniuOssVideo(bytes,"IT⽼⻬");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
七⽜图⽚产品
package com.itlaoqi.abstractfactory.qiniu.product;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
public class QiniuOssImage implements OssImage {
private byte[] bytes;
public QiniuOssImage(byte[] bytes,String watermark){
this.bytes = bytes;
System.out.println("[七⽜云]图⽚已上传⾄七⽜云OSS,URL:http://oss.qini
u.com/xxxxxxx.jpg");
System.out.println("[七⽜云]已⽣成缩略图,尺⼨800X600像素");
System.out.println("[七⽜云]已为图⽚新增⽔印,⽔印⽂本:" + watermark +
",⽂本颜⾊#cccccc");
System.out.println("[七⽜云]已将图⽚AI增强为1080P⾼清画质");
}
@Override
public String getThumb() {
return "http://oss.qiniu.com/xxxxxxx_thumb.jpg";
}
@Override
public String getWatermark() {
return "http://oss.qiniu.com/xxxxxxx_watermark.jpg";
}
@Override
public String getEnhance() {
return "http://oss.qiniu.com/xxxxxxx_enhance.jpg";
}
}
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
七⽜视频产品
package com.itlaoqi.abstractfactory.qiniu.product;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
public class QiniuOssVideo implements OssVideo {
private byte[] bytes;
public QiniuOssVideo(byte[] bytes, String watermark) {
this.bytes = bytes;
System.out.println("[七⽜云]视频已上传⾄阿⾥云OSS,URL:http://oss.qiniu.com/xxx.mp4");
System.out.println("[七⽜云]1080P转码成功,码率:3500K");
System.out.println("[七⽜云]720P转码成功,码率:2500K");
}
@Override
public String get720P() {
return "http://oss.qiniu.com/xxx_720p_2500.mp4";
}
@Override
public String get1080P() {
return "http://oss.qiniu.com/xxx_1080p_3500.mp4";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 阿⾥云实现
package com.itlaoqi.abstractfactory.aliyun;
import com.itlaoqi.abstractfactory.factory.AbstractOssFactory;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
import com.itlaoqi.abstractfactory.aliyun.product.AliyunOssImage;
import com.itlaoqi.abstractfactory.aliyun.product.AliyunOssVideo;
public class AliyunOssFactory implements AbstractOssFactory {
@Override
public OssImage uploadImage(byte[] bytes) {
return new AliyunOssImage(bytes,"IT⽼⻬",true);
}
@Override
public OssVideo uploadVideo(byte[] bytes) {
return new AliyunOssVideo(bytes,"IT⽼⻬");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
阿⾥云图⽚产品
package com.itlaoqi.abstractfactory.aliyun.product;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
public class AliyunOssImage implements OssImage {
private byte[] bytes;
public AliyunOssImage(byte[] bytes, String watermark,boolean transpare
nt){
this.bytes = bytes;
System.out.println("[阿⾥云]图⽚已上传⾄阿⾥云OSS,URL:http://oss.aliyun.com/xxxxxxx.jpg");
System.out.println("[阿⾥云]已⽣成缩略图,尺⼨640X480像素");
System.out.println("[阿⾥云]已为图⽚新增⽔印,⽔印⽂本:" + watermark +",⽂本颜⾊:#aaaaaa,背景透明:" + transparent);
System.out.println("[阿⾥云]已将图⽚AI增强为4K极清画质");
}
@Override
public String getThumb() {
return "http://oss.aliyun.com/xxxxxxx_thumb.jpg";
}
@Override
public String getWatermark() {
return "http://oss.aliyun.com/xxxxxxx_watermark.jpg";
}
@Override
public String getEnhance() {
return "http://oss.aliyun.com/xxxxxxx_enhance.jpg";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
阿⾥云视频产品
package com.itlaoqi.abstractfactory.aliyun.product;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
public class AliyunOssVideo implements OssVideo {
private byte[] bytes;
public AliyunOssVideo(byte[] bytes, String watermark) {
this.bytes = bytes;
System.out.println("[阿⾥云]视频已上传⾄阿⾥云OSS,URL:http://oss.aliyun.com/xxx.mp4");
System.out.println("[阿⾥云]720P转码成功,码率:5000K");
System.out.println("[阿⾥云]1080P转码成功,码率:7000K");
}
@Override
public String get720P() {
return "http://oss.aliyun.com/xxx_720p.mp4";
}
@Override
public String get1080P() {
return "http://oss.aliyun.com/xxx_1080p.mp4";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
⽤户端根本不需要了解阿⾥云/七⽜云的处理细节,直接创建⼯⼚对象就好啦。你建哪个⼯⼚,就采⽤哪个⼯⼚⽣产品,产品的特质也不同。
同时,未来接⼊腾讯云也不需要修改现在的代码,按上⾯的套路实现⼀个⼯⼚和图⽚、视频对象即可
package com.itlaoqi.abstractfactory;
import com.itlaoqi.abstractfactory.aliyun.AliyunOssFactory;
import com.itlaoqi.abstractfactory.factory.AbstractOssFactory;
import com.itlaoqi.abstractfactory.factory.product.OssImage;
import com.itlaoqi.abstractfactory.factory.product.OssVideo;
import com.itlaoqi.abstractfactory.qiniu.QiniuOssFactory;
public class Client {
public static void main(String[] args) {
// AbstractOssFactory factory = new AliyunOssFactory();
AbstractOssFactory factory = new QiniuOssFactory();
OssImage ossImage = factory.uploadImage(new byte[1024]);
OssVideo ossVideo = factory.uploadVideo(new byte[1024]);
System.out.println(ossImage.getThumb());
System.out.println(ossImage.getWatermark());
System.out.println(ossImage.getEnhance());
System.out.println(ossVideo.get720P());
System.out.println(ossVideo.get1080P());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 八、总结
由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化。
← 第01章:单例模式 第03章:工厂方法模式 →
