之前的文章介绍了工厂模式,这篇文章介绍工厂模式的强化版本抽象工厂模式(Abstract Factory Pattern) 。
我们知道工厂模式是用于在延迟创建具体的对象,抽象工厂模式可以看作是面向工厂模式的工厂模式,所以,我称它为强化版本。
我个人并不喜欢抽象工厂模式,因为它一定是为了应付复杂的系统。
试想一下,谁喜欢负责的东西呢?
但软件行业,复杂的业务其实代表了更精细化的需求,所以,这也是它的意义所在。
抽象工厂模式是为了应对产品线,产品线有不同的分支,每个分支代表不同的维度。
还是以前面工厂模式中的出行举例子。
从广州到深圳出行,乘坐交通工具的话有:飞机、高铁、大巴等等选项。
但另外一种维度,我不考虑具体的交通工具,我只考虑舒适程度,那么我就有下面的选择:
我们都知道,软件开发要拥抱变化,当面对同一个客户,他的需求发生变化时,我们的代码也需要做调整。
抽象工厂模式可以应对这种需求。
首先,交通工具类型用一个工厂表示,这和之前的文章无异。
然后,照葫芦画瓢,再弄一个档次工厂。
然后,再针对交通工具和档次工厂设计一个工厂
最后,整体 UML 图就出来了。
当 UML 图出来后,剩下的就是编码工作了。
Transportation.java
public interface Transportation {
void move(String dst);
}
Bus.java
public class Bus implements Transportation{
@Override
public void move(String dst) {
// TODO Auto-generated method stub
System.out.println("Take a bus to "+dst);
}
}
Tran.java
public class Train implements Transportation{
@Override
public void move(String dst) {
// TODO Auto-generated method stub
System.out.println("Take a train to "+dst);
}
}
Plane.java
public class Plane implements Transportation{
@Override
public void move(String dst) {
// TODO Auto-generated method stub
System.out.println("Take a plane to "+dst);
}
}
然后创建 TransportationFactory
public class TransportationFactory extends AbstractFactory {
@Override
public Transportation getTransportation(String type){
if(type == null){
return null;
}
if(type.equalsIgnoreCase("TRAIN")){
return new Train();
} else if(type.equalsIgnoreCase("BUS")){
return new Bus();
} else if(type.equalsIgnoreCase("PLANE")){
return new Plane();
}
return null;
}
@Override
public Degree getDegree(int type) {
// TODO Auto-generated method stub
return null;
}
}
交通工具类相关代码完成后,就创建消费档次借口及实现类
Degree.java
public interface Degree {
void move(int type);
}
Economical.java
public class Economical implements Degree {
@Override
public void move(int type) {
// TODO Auto-generated method stub
System.out.println("本次乘坐经济档次交通工具出行");
}
}
Comfortable.java
public class Comfortable implements Degree {
@Override
public void move(int type) {
// TODO Auto-generated method stub
System.out.println("本次乘坐舒适型交通工具出行");
}
}
Luxuroius.java
public class Luxurious implements Degree {
@Override
public void move(int type) {
// TODO Auto-generated method stub
System.out.println("本次乘坐豪华型交通工具出行");
}
}
然后,创建相关的工厂 DegreeFactory
public class DegreeFactory extends AbstractFactory {
@Override
public Transportation getTransportation(String type){return null;}
@Override
public Degree getDegree(int type){
switch(type)
{
case 0:
return new Economical();
case 1:
return new Comfortable();
case 2:
return new Luxurious();
default:
break;
}
return null;
}
}
AbstractFactory.java
public abstract class AbstractFactory {
public abstract Transportation getTransportation(String type);
public abstract Degree getDegree(int type);
}
有了抽象类,还需要一个工厂创建器 FactoryCreator
public class FactoryCreator {
public AbstractFactory getFactory(String type) {
if(type == null){
return null;
}
if(type.equalsIgnoreCase("Tranportation")){
return new TransportationFactory();
}
return new DegreeFactory();
}
}
最后,编写测试 Demo AbstractFactoryDemo.java
public class AbstractFactoryDemo {
public static void main(String[] args) {
FactoryCreator creator = new FactoryCreator();
TransportationFactory factory = (TransportationFactory)creator.getFactory("Tranportation");
Transportation transportation = factory.getTransportation("train");
transportation.move("深圳");
DegreeFactory factory1 = (DegreeFactory)creator.getFactory("Degree");
Degree degree = factory1.getDegree(2);
degree.move(2);
}
}
最终结果如下:
Take a train to 深圳
本次乘坐豪华型交通工具出行
可以看到,代码正常运行。
上面的例子很简单,其实实际开发中会稍微复杂。
比如,我们要出行,一般会通过旅行社,那么不同的旅行社给出的方案是不一样的。
如果把每一个旅行社当作是一个工厂的话,抽象工厂方法在这里也会大放异彩。
有些旅行社出方案时会考虑交通工具、目的地,有些旅行社则更多以时长、价格、舒适度为卖点。
把这些因素:
分别建立一个接口,那么可以自由重组好多种方案。
不同的 Factory 其实是可以共享一些接口的。
放出一张 UML 示意图,代码大家自己完成。