前言
说实话,就算是假期,每日一到两篇的更新还是有点累的,写一篇长一点的文章差不多一个下午就过去了,但是我个人觉得写文章比较适合我学习,变写的同时能知道哪些不懂,顺便再去复习一下,也算是个不错的方式吧。
今天就来聊聊抽象工厂模式。
正文
概念
之前我们讲过工厂模式,工厂模式的特点是对象的创建交给工厂来实现,隐藏内部逻辑,但是工厂模式也有相应的缺点,那就是一个工厂只能生产一类产品,但往往一个工厂需要有创建多种商品的功能,而抽象工厂模式就是为了解决这个问题。
抽象工厂模式简单说就是一个大工厂下有几个小工厂,小工厂实现大工厂的所有产品。它解决的就是工厂模式下,每个工厂只能创建一类产品的缺点。
实现
就从上次的工厂模式的案例说起,现在一个工厂既可以生产游戏,又可以生产周边,我们就从这个例子来实现抽象工厂模式。
首先是游戏接口及其实体类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public interface Game { void test(); } public class GameA implements Game{ @Override public void test() { System.out.println("this is Game A"); } } public class GameB implements Game{ @Override public void test() { System.out.println("this is Game B"); } } public class GameC implements Game{ @Override public void test() { System.out.println("this is Game C"); } }
|
接下来创建周边接口及其实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public interface Hobby { public void test(); } public class HobbyA implements Hobby{ @Override public void test() { System.out.println("this is HobbyA"); } } public class HobbyB implements Hobby{ @Override public void test() { System.out.println("this is HobbyB"); } } public class HobbyC implements Hobby{ @Override public void test() { System.out.println("this is HobbyC"); } }
|
接下来是创建一个抽象工厂
1 2 3 4
| public abstract class AbstractFactory { public abstract Game getGame(String name); public abstract Hobby getHobby(String name); }
|
创建两个工厂继承抽象工厂
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
| public class GameFactory extends AbstractFactory{ public Game getGame(String name){ if (name == null){ return null; }
if (name.equalsIgnoreCase("GameA")){ return new GameA(); }else if (name.equalsIgnoreCase("GameB")){ return new GameB(); }else if (name.equalsIgnoreCase("GameC")){ return new GameC(); } return null; }
@Override public Hobby getHobby(String name) { return null; } }
public class HobbyFactory extends AbstractFactory{ @Override public Game getGame(String name) { return null; }
@Override public Hobby getHobby(String name) { if (name == null){ return null; }
if (name.equalsIgnoreCase("HobbyA")){ return new HobbyA(); }else if (name.equalsIgnoreCase("HobbyB")){ return new HobbyB(); }else if (name.equalsIgnoreCase("HobbyC")){ return new HobbyC(); } return null; } }
|
接下来是创建工厂生成器来获取相应的工厂
1 2 3 4 5 6 7 8 9 10
| public class FactoryBuilder { public static AbstractFactory getFactory(String factoryName){ if (factoryName.equalsIgnoreCase("Game")){ return new GameFactory(); }else if (factoryName.equalsIgnoreCase("Hobby")){ return new HobbyFactory(); } return null; } }
|
创建客户端进行调用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Client { public static void main(String[] args) { AbstractFactory gameFactory = FactoryBuilder.getFactory("Game"); AbstractFactory hobbyFactory = FactoryBuilder.getFactory("Hobby");
Game game = gameFactory.getGame("GameA"); game.test();
Hobby hobby = hobbyFactory.getHobby("HobbyC"); hobby.test();
} }
|
以上我们就简单实现了抽象工厂模式,其实原理还是很简单的。
后续思考
当抽象工厂模式中,产品只有一个的时候,抽象工厂模式就是工厂模式,反过来,当产品由一个变多个时,工厂模式变为抽象工厂模式。
那在抽象工厂模式中,添加一个工厂需要怎么操作呢?
很简单,我们只需要创建一个继承于AbstractFactory的工厂就可以了。
那添加一个新的产品呢?
首先当然需要添加一个新的接口与对应的实现类,其次抽象工厂中,需要添加该产品,导致所有继承于抽象类的工厂都必须添加这个产品,只是可以不生产而已,代码上的话,如果工厂很多,就需要添加这些工厂中的重写方法。
优缺点
抽象工厂模式的优点在于解决工厂模式中只能创建单一产品的缺点。并且拥有工厂模式的优点。
而缺点在于产品的扩展较为麻烦,上文提到,添加产品,需要修改抽象类,又需要在实现的工厂中增加代码。
总结
本文简单谈了谈抽象工厂模式,这个模式在开发中很少用到,对整体的架构不利于扩展,修改的话又十分麻烦。工厂模式对于框架的设计还是较为常用的,比如spring的getBean,又如java中的线程池(可以看看线程池的文章),等等很多例子。总之这个工厂模式还是比较重要的。