抽象工厂模式和前面介绍工厂方法模式很相似,但是它比工厂方法模式的扩展性要更好。在工厂方法模式中,我们将创建实例的逻辑都放在了一个统一的工厂类中,根据参数和判断语句实例不同的实现类。如果有新的实现类,我们就需要通过修改工厂类来支持新的实现类,使用抽象工厂模式就可以避免修改原有的工厂类来支持新的实现类。
下面还是以搜索引擎为例,来看看抽象工厂模式的套路,假设有三个搜索引擎的实现,分别是Google,Baidu,Yahoo,我们需要根据不同语言返回不同的搜索引擎。
首先和工厂方法模式一样,定义ISearchEngine
接口和search
方法。
public interface ISearchEngine {
String search(String text);
}
然后是两个ISearchEngine
的实现类,Google,Baidu。
1public class Google implements ISearchEngine {
2 @Override
3 public String search(String text) {
4 return "Results in English";
5 }
6}
7
8public class Baidu implements ISearchEngine {
9 @Override
10 public String search(String text) {
11 return "中文结果";
12 }
13}
跟之前工厂方法模式不同的是,工厂类不再直接创建返回实现类,而是通过传入的抽象工厂类来创建并返回。
public abstract class SearchEngineFactory {
public abstract ISearchEngine create();
public static ISearchEngine createEngine(SearchEngineFactory factory) {
return factory.create();
}
}
然后为不同的搜索引擎实现类也创建相应的工厂类实现。
1public class GoogleFactory extends SearchEngineFactory {
2 @Override
3 public ISearchEngine create() {
4 return new Google();
5 }
6}
7
8public class BaiduFactory extends SearchEngineFactory {
9 @Override
10 public ISearchEngine create() {
11 return new Baidu();
12 }
13}
假如有新的ISearchEngine
实现类 Yahoo,我们无需改动SearchEngineFactory,只需要在为Yahoo创建一个工厂实现类即可。
public class YahooFactory extends SearchEngineFactory {
@Override
public ISearchEngine create() {
return new Yahoo();
}
}
ISearchEngine engine = SearchEngineFactory.createEngine(new YahooFactory());
抽象工厂模式除了有工厂方法模式的两个优点外,还进一步提高了可扩展性,它将创建实例的逻辑从工厂类剥离,当需要扩展更多实现类时不再需要修改原有的工厂类,但是抽象工厂模式增加了代码的复杂性,对于实现类已知的情况使用工厂方法模式即可,但是对于实现类不完全可知,比如对外提供SDK,使用者可能有自己的实现类的情况,使用抽象工厂模式会更合适。