# 《Java极简设计模式》第02章:抽象工厂模式(AbstractFactoty)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:用最简短的篇幅介绍抽象工厂模式最核心的知识,理解抽象工厂模式的设计精髓,并能够灵活运用到实际项目中,编写可维护的代码。

# 一、概述

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象⼯⼚也可以称作其他⼯⼚的⼯⼚,它可以在抽象⼯⼚中创建出其他⼯⼚,与⼯⼚模式⼀样,都是⽤来解决接⼝选择的问题,同样都属于创建型模式

# 二、为何使用

工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。

为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

# 三、实用性

  1. 一个系统要独立于它的产品的创建、组合和表示时。
  2. 一个系统要由多个产品系列中的一个来配置时。
  3. 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  4. 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

# 四、参与者

  1. AbstractFactory 声明一个创建抽象产品对象的操作接口。
  2. ConcreteFactory 实现创建具体产品对象的操作。
  3. AbstractProduct 为一类产品对象声明一个接口。
  4. ConcreteProduct 定义一个将被相应的具体工厂创建的产品对象。 实现AbstractProduct接口。
  5. Client 仅使用由AbstractFactory和AbstractProduct类声明的接口

# 五、类图


# 六、示例一

  • AbstractFactory

定义抽象工程类IAnimalFactory

public interface IAnimalFactory {
    /**
     * 定义创建Icat接口实例的方法
     * @return
     */
    ICat createCat();
    /**
     * 定义创建IDog接口实例的方法
     * @return
     */
    IDog createDog();
}
1
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();
    }
}
1
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();
    }

}
1
2
3
4
5
6
7
8
9
10
11
  • AbstractProduct

定义抽象工厂中要生产的抽象产品接口ICat和IDog

public interface ICat {
    /**
     * 定义方法
     */
    void eat();
}
1
2
3
4
5
6
public interface IDog {
	 /**
     * 定义方法
     */
    void eat();
}
1
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!");
    }
}
1
2
3
4
5
6
public class BlackDog implements IDog {
	@Override
    public void eat() {
        System.out.println("The black dog is eating");
    }
}
1
2
3
4
5
6
public class WhiteCat implements ICat {
	@Override
    public void eat() {
        System.out.println("The white cat is eating!");
    }
}
1
2
3
4
5
6
public class WhiteDog implements IDog {
	@Override
    public void eat() {
        System.out.println("The white dog is eating!");
    }

}
1
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();
	}
}
1
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!
1
2
3
4

# 七、示例二

公司早期接⼊七⽜云OSS(对象存储服务)上传图⽚与视频,后因业务调整,公司要求额外⽀持阿⾥云、腾讯云等其他云服务商,并且可以对客户提供外界访问。

设计要求为:允许在不破坏原有代码逻辑情况下,实现对任意三⽅云⼚商的接⼊。

image-20241119172424093

抽象⼯⼚模式

顾名思义即为⼯⼚的⼯⼚,通过构建顶层的抽象⼯⼚和抽象的产品,屏蔽系列产品的构建过程。

抽象⼯⼚与抽象的系列产品接⼝

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();
}
1
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⽼⻬");
 }
}
1
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("[七⽜云]图⽚已上传⾄七⽜云OSSURL: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";
 }
}
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

七⽜视频产品

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";
 }
}
1
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⽼⻬");
 }
}
1
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";
 }
}
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

阿⾥云视频产品

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";
 }
}
1
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());
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 八、总结

由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他地方无需一点变换,就有可能将系统功能进行改头换面的变化。