设计模式(四)——一文搞清楚三种工厂模式
本系列博客是自己在学习设计模式过程中收集整理的文章集合,其他文章参看设计模式传送门
本文是转载文章,原文请参见原文
之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略。
这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml中,jdbc连接数据库等)利用好工厂模式对程序的设计很有用处。
工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类。也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口。下面结合例子分析三者的区别。
简单工厂模式
首先是简单工厂模式,这里以工厂生产产品为例。
产品类的共同接口
1 1 package factory;
2 2 /**
3 3 *
4 4 * @author CIACs
5 5 *
6 6 */
7 7 public interface Product {
8 8 //声明类所需继承的共同接口,也可以是抽象类
9 9 }
产品A
1 package factory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class ProductA implements Product {
8 public ProductA() {
9 System.out.println("ProductA");
10 }
11 }
产品B
1 package factory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class ProductB implements Product {
8 public ProductB() {
9 System.out.println("ProductB");
10 }
11 }[![复制代码](https://common.cnblogs.com/images/copycode.gif)](javascript:void(0);
工厂类
1 package factory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class Factory {
8 //可以在工厂类中添加任何你所需要的逻辑
9 public static Product create(String str)
10 {
11 //生成ProductA
12 if(str.equalsIgnoreCase("ProductA"))
13 {
14 return new ProductA();
15 }
16 else
17 //生成ProductB
18 if(str.equalsIgnoreCase("ProductB"))
19 {
20 return new ProductB();
21 }
22 return null;
23 }
24
25 }
客户端
1 package factory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class Client {
8 public static void main(String[] args) {
9 //调用Factory的静态方法生成所要的类
10 Factory.create("productA");
11 Factory.create("ProductB");
12 }
13 }
控制台输出结果:
简单工厂模式实现了生成产品类的代码跟客户端代码分离,在工厂类中你可以添加所需的生成产品的逻辑代码,但是问题来了,优秀的java代码是符合“开放-封闭”原则的,也就是说对扩展开发,对修改关闭,如果你要加一个产品类C,你就要修改工厂类里面的生成产品的代码,在这里你就要增加if-else判断。对于这个问题,我们的工厂方法模式就可以解决这个问题。
工厂方法模式
接下来是工厂方法模式
产品类中增加了ProductC(其他产品类的代码是可以重用上面的,只要把包名更改了就行)。
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7
8 public class ProductC implements Product {
9 public ProductC() {
10 System.out.println("productC");
11 }
12 }
声明工厂接口
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public interface Factory {
8 //声明产生产品类的方法
9 public Product createProduct();
10 }
产生ProductA的FactoryA
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class FactoryA implements Factory {
8 //实现工厂类的方法生成产品类A
9 public Product createProduct()
10 {
11 return new ProductA();
12 }
13
14 }
产生ProductB的FactoryB
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class FactoryB implements Factory {
8 //实现工厂类的方法生成产品类B
9 public Product createProduct()
10 {
11 return new ProductB();
12 }
13 }
产生ProductC的FactoryC
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class FactoryC implements Factory {
8 //实现工厂类的方法生成产品类C
9 public Product createProduct()
10 {
11 return new ProductC();
12 }
13 }
客户端
1 package factoryMehtod;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class Client {
8 public static void main(String[] args) {
9 Factory factory;
10 factory = new FactoryA();
11 factory.createProduct();
12 factory = new FactoryB();
13 factory.createProduct();
14 factory = new FactoryC();
15 factory.createProduct();
16 }
17 }
控制台输出结果:
工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。
但是这还是有缺点的,如果产品类过多,我们就要生成很多的工厂类。假如我们要实现的产品接口不止一个,也就是有多个产品接口,不同产品接口有对应的产品族。
什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。
抽象工厂模式
最后是抽象工厂模式,在这里我们为不同产品附加上对应的礼物,就是说ProductA中会有GiftA。
增加的Gift接口
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public interface Gift {
8 //声明产品赠品的接口,当然也可以是抽象类,同样为了简单就不声明方法了
9 }
GiftA类
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class GiftA implements Gift {
8 public GiftA()
9 {
10 System.out.println("GiftA");
11 }
12 }
GiftB类
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class GiftB implements Gift {
8 public GiftB()
9 {
10 System.out.println("GiftB");
11 }
12 }
Factory接口
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *声明Product类工厂和Gift类工厂的工同工厂接口
6 */
7 public interface Factory {
8 public Product createProduct();
9 public Gift createGift();
10
11 }
生成ProductA和GiftA的FactoryA
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *FactoryA可以生成ProductA和GiftA
6 */
7 public class FactoryA implements Factory {
8 @Override
9 public Product createProduct()
10 {
11 return new ProductA();
12 }
13 @Override
14 public Gift createGift()
15 {
16 return new GiftA();
17 }
18 }
生成ProductB和GiftB的FactoryB
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *FactoryB可以生成ProductB和GiftB
6 */
7 public class FactoryB implements Factory {
8 @Override
9 public Product createProduct() {
10 return new ProductB();
11 }
12 @Override
13 public Gift createGift() {
14 return new GiftB();
15 }
16
17 }
客户端
1 package abstractFactory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public class Client {
8 public static void main(String[] args) {
9 Factory factory;
10 factory = new FactoryA();
11 factory.createProduct();
12 factory.createGift();
13 factory = new FactoryB();
14 factory.createProduct();
15 factory.createGift();
16 }
17 }
控制台输出结果:
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。我们在使用中要注意使用抽象工厂模式的条件。