应用场景
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
首先我们看一下百度百科对抽象工厂模式的图分析。
大致流程是这样,创建一个接口creator,一组相关或者相互依赖的对象就是ProductA和ProductB以及它们具体的实现类,而上面又提到说不是返回的具体的类,所以我们返回的应该是接口或者抽象类,那么上述类图当中,则是指的ProductA和ProductB接口。
抽象工厂模式实例
首先给出我们的产品族,图的右半部分。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
27
28
29
30
31
32package com.liu.abstract1;
interface ProductA{
void methodA();
}
interface ProductB{
void methodB();
}
class ProductA1 implements ProductA{
public void methodA() {
// TODO Auto-generated method stub
System.out.println("产品A系列中1型号产品的方法");
}
}
class ProductA2 implements ProductA{
public void methodA() {
// TODO Auto-generated method stub
System.out.println("产品A系列中2型号产品的方法");
}
}
class ProductB1 implements ProductB{
public void methodB(){
System.out.println("产品B系列中1型号产品的方法");
}
}
class ProductB2 implements ProductB{
public void methodB(){
System.out.println("产品B系列中2型号产品的方法");
}
}
然后再给出创造产品的接口。1
2
3
4
5
6package com.liu.abstract1;
public interface Creator {
ProductA createProductA();
ProductB createProductB();
}
创建第一种产品库1
2
3
4
5
6
7
8
9
10package com.liu.abstract1;
public class ConcreteCreator1 implements Creator{
public ProductA createProductA(){
return new ProductA1();
}
public ProductB createProductB(){
return new ProductB1();
}
}
创建第二种产品库1
2
3
4
5
6
7
8
9
10package com.liu.abstract1;
public class ConcreteCreator2 implements Creator{
public ProductA createProductA(){
return new ProductA2();
}
public ProductB createProductB(){
return new ProductB2();
}
}
创建测试类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.liu.abstract1;
public class Client {
public static void main(String[] args) {
Creator creator=new ConcreteCreator1();
ProductA productA=creator.createProductA();
ProductB productB=creator.createProductB();
productA.methodA();
productB.methodB();
creator=new ConcreteCreator2();
productA=creator.createProductA();
productB=creator.createProductB();
productA.methodA();
productB.methodB();
}
}
输出结果1
2
3
4产品A系列中1型号产品的方法
产品B系列中1型号产品的方法
产品A系列中2型号产品的方法
产品B系列中2型号产品的方法
这就是一个简单的抽象工厂模式,一开始我看到抽象工厂模式,还以为他是要用抽象类和抽象方法,原来是我误解了,抽象工厂模式就是把原来的工厂糅合在一起,再变成几种工厂,随意组合。
这个相对比较简单。
深入理解
为了更深入的理解,我打算研究JDK源码,List接口源码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package java.util;
public interface List<E> extends Collection<E> {
Iterator<E> iterator();//一种产品
Object[] toArray();
<T> T[] toArray(T[] a);
ListIterator<E> listIterator();//另外一种产品
ListIterator<E> listIterator(int index);
}
这里面肯定是去掉了源码的很多方法,为了看着更简便。
其中ListIterator是Iterator的子接口,但归根到底,它其实属于另外一种产品,为什么这么说呢,ListIterator不是Iterator的子接口吗,怎么能算是另外一种产品呢?这是因为我们listIterator方法的返回类型是ListIterator,而不是Iterator,所以两者的功能是不同的,比如ListIterator还可以向前移动。
我们可以认为这两个方法产生的一个是只能向后移动的迭代器,一个是可以前后移动的迭代器,这算是两种产品,相当于上面的ProductA和ProductB。
这个设计可以看做是一个抽象工厂模式,List接口定义了两种生产不同产品的方法,这属于两个系列的产品,不过由于产品接口本身的继承关系,两者的实现类也会被做成继承的关系。
根据这个图,与上面的简单的对比一下。
- List,是抽象工厂的角色,它有两个制造产品的方法,iterator和listIterator,相当于Creator。
- ListItertor和Iterator都是抽象产品,相当于ProductA和ProductB。其中ListIterator有两个实现类,分别是AbstractList.ListItr和LinkedList.ListIter,相当于ProductA1和ProductA2.Iterator的实现类为AbstractList.Itr,相当于ProductB1,但是没有B2.
- LinkedList是其中一个具体的工厂类,相当于ConcreteCreator1,实现抽象工厂List,它制造的两个具体产品分别是LinkedList.ListItr和AbstractList.Itr.
- 同样的,ArrayList是一个具体的工厂类,相当于ConcreteCreator2,实现抽象工厂List,它制造的两个具体产品分别是AbstractList.ListItr和AbstractList.Itr。
总结
Iterable接口是List的父接口,所以它只负责一个产品Iterator的制造,所以是工厂方法模式,而List接口扩展了Iterable接口,又添加了一个制造产品的方法,即又添加了一个系列的产品,所以就成为了抽象工厂模式。
给出上述两个类图的对应关系。
1.Creator=List
2.ConcreteCreator1=ArrayList
3.ConcreteCreator2=LinkedList
4.ProductA=Iterator
5.ProductB=ListIterator
6.ProductA1=AbstractList.Itr
7.ProductA2=无(具体的A产品2在第一个类图中是没有的,但这并不影响整个体系)
8.ProductB1=AbstractList.ListItr
9.ProductB2=LinkedList.ListItr
ArrayList和LinkedList分别是List接口的两种实现,前者是基于数组操作,后者是基于链表。两者都可以产生Iterator和ListIterator,而Iterator的实现都是在AbstractList中实现的,是一样的处理方式,而对于ListIterator的实现却不相同,AbstractList.ListItr是基于数组的操作,LinkedList.ListItr是基于链表的操作方式。
所以抽象工厂模式一般是为了处理抽象产品多于一个的问题,而且这些产品多数情况下是有关系的,像上述JAVA集合框架的例子当中,Iterator和ListIterator就是继承的关系,大部分情况下,很少会使用抽象工厂模式去创造一批毫无关系的产品。
基于抽象工厂一旦定义,抽象产品的个数就已经固定,所以最好在抽象产品的个数不太会变化的情况下使用抽象工厂模式,当然,我们可以使用继承去弥补抽象工厂模式的这一不足,创造另外一个继承体系去扩展现有的框架。工厂模式总结
简单工厂模式1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//抽象产品
interface Product{}
//具体产品
class ProductA implements Product{}
class ProductB implements Product{}
//产品工厂(下一步就是它的进化,就变成了工厂方法模式)
public class ProductFactory {
private ProductFactory(){}
public static Product getProduct(String productName){
if (productName.equals("A")) {
return new ProductA();
}else if (productName.equals("B")) {
return new ProductB();
}else {
return null;
}
}
}
工厂模式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
27//抽象产品
interface Product{}
//具体产品
class ProductA implements Product{}
class ProductB implements Product{}
//将简单工厂中的工厂给抽象成接口
interface Factory{
Product getProduct();
}
//具体的工厂A,创造产品A
class FactoryA implements Factory{
public Product getProduct() {
return new ProductA();
}
}
//具体的工厂B,创造产品B
class FactoryB implements Factory{
public Product getProduct() {
return new ProductB();
}
}
抽象工厂模式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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44//抽象产品
interface Product{}
//具体产品
class ProductA implements Product{}
class ProductB implements Product{}
//多了一个抽象产品1
interface Product1{}
//具体产品1
class Product1A implements Product1{}
class Product1B implements Product1{}
//原有的工厂方法模式的工厂里添加一个方法
interface Factory{
Product getProduct();
//添加另外一个产品族的创造方法
Product1 getProduct1();
}
//具体的工厂A,创造产品A
class FactoryA implements Factory{
public Product getProduct() {
return new ProductA();
}
//添加相应的实现
public Product1 getProduct1() {
return new Product1A();
}
}
//具体的工厂B,创造产品B
class FactoryB implements Factory{
public Product getProduct() {
return new ProductB();
}
//添加相应的实现
public Product1 getProduct1() {
return new Product1B();
}
}
与工厂方法对比下就发现,多了一个产品系列叫Product1,工厂接口里多了一个方法,叫getProduct1,所以抽象工厂模式就是工厂方法模式添加了抽象产品所演变而来的。
1,首先从简单工厂进化到工厂方法,是因为工厂方法弥补了简单工厂对修改开放的弊端,即简单工厂违背了开闭原则。
2,从工厂方法进化到抽象工厂,是因为抽象工厂弥补了工厂方法只能创造一个系列的产品的弊端。