前言
什么是工厂我就不在介绍了,我写的简单工厂已经介绍的很详细了,文中有链接。不论是对比简单工厂还是工厂方法,抽象工厂看起来都是一种很麻烦的模式,抽象工厂和工厂方法其实是完成了类似的功能,上期我们介绍工厂方法的时候我说过,对于工厂方法的扩展,添加一种产品是很容易的,而且不用修改原有的代码,而如果对已经存在的产品去细分,则没办法符合开闭原则了(在菜单上如果我添加新的产品蛋炒饭,工厂方法可以很容易做到,但是如果我说把菜单里的面条分成大碗小碗,这就是工厂方法模式做不到的了),因此我们需要抽象工厂来完成这件事。
情景引入
我们依然以菜单(接口)为例,依然有两种饭,米饭和面条,但是改为抽象类,然后新建四个子类,分别是大碗小碗的米饭和面条,而具体工厂本次则分为大碗工厂和小碗工厂,本程序是在工厂方法例子上进行的修改,但是可以看出改动幅度较大,如果阅读了我写的简单工厂和工厂方法应该很容易能搞懂程序的来世今生。
简单工厂:https://blog.youkuaiyun.com/zhen921/article/details/81986986
工厂方法:https://blog.youkuaiyun.com/zhen921/article/details/82021274
先理解举例类图和程序,后面再做分析
下面是我程序的类图

Java源程序如下
菜单类
package abstractfactory_06;
public interface Menu {
public void getMeal();
}
面条类
package abstractfactory_06;
public abstract class Noodles implements Menu{
public abstract void getMeal();
}
大碗面
package abstractfactory_06;
public class BigNoodles extends Noodles{
public void getMeal() {
System.out.println("大份面条");
}
}
小碗面
package abstractfactory_06;
public class SmallNoodles extends Noodles{
public void getMeal() {
System.out.println("小份面条");
}
}
米饭类
package abstractfactory_06;
public abstract class Rice implements Menu{
public abstract void getMeal() ;
}
大碗米饭
package abstractfactory_06;
public class BigRice extends Rice{
public void getMeal() {
System.out.println("大份米饭");
}
}
小碗米饭
package abstractfactory_06;
public class SmallRice extends Rice{
public void getMeal() {
System.out.println("小份米饭");
}
}
抽象工厂类
package abstractfactory_06;
public abstract class FoodFactory {
public abstract Menu getRice();//返回米饭实例
public abstract Menu getNoodles();//返回面条实例
}
大碗工厂
package abstractfactory_06;
public class BigFactory extends FoodFactory{
public Menu getRice() {
return new BigRice();
}
public Menu getNoodles() {
return new BigNoodles();
}
}
小碗工厂
package abstractfactory_06;
public class SmallFactory extends FoodFactory{
public Menu getRice() {
return new SmallRice();
}
public Menu getNoodles() {
return new SmallNoodles();
}
}
客户端
package abstractfactory_06;
public class Client {
public static void main(String[] args) {
FoodFactory ff=new BigFactory();
Menu rice=ff.getRice();//拿到米饭对象
rice.getMeal();
ff=new SmallFactory();
rice=ff.getRice();
rice.getMeal();
}
}
运行结果

程序分析
-
- 实例中类图较多,容易混淆,但看着类图把脉络搞清就能理解,本例中,我们把米饭和面条两种产品做了抽象处理,让子类实现,并且做出大碗小碗,而两个具体工厂一个负责大碗对象的创建,一个负责小碗对象的创建。
- 如果想扩展程序,比如说想做中碗,那么很显然,我们只需要创建中 碗类去继承各个产品,而且我们只需要建建一个中碗工厂,我们就可以做中碗的饭了,这样我们就实现了在不改动原有程序的前提下实现了对产品的细分。
- 但是如果想增加产品,比如加蛋炒饭,那就没办法维持开闭原则了,因为加产品就得分大碗小碗,那大碗工厂小碗工厂则全要更改,这样违背了设计模式的初衷,因此抽象工厂适合切分现有产品,不适合添加新的产品,而工厂方法模式恰恰相反
既然知道抽象工厂的作用,那我们就回来总结一下他的特点。
定义
抽象工厂模式提供一个接口,用于创建相关或者依赖对象的家族,而不需要指明具体类
应用场景
当你想建立产品的家族或者产品集合而不关心具体的产品都有哪些的时候
优点
-
- 扩展产品家族成员十分方便,符合了开闭原则
- 客户和具体产品之间实现了解耦
缺点
-
- 扩展产品类别很困难
- 类更多,理解起来更费劲
角色组成
由类图可以看出,主要角色有四种
| 抽象产品 | 定义工厂方法所创建的对象 |
| 具体产品 | 继承抽象产品的具体产品 |
| 抽象工厂 | 声明创建对象的方法,返回一个产品类型的对象 |
| 具体工厂 | 实现创建具体产品的方法,并返回具体产品对象 |
写在最后
所有工厂的最终目的都是为了封装对象的创建,而之所以有两种设计模式,是由于设计目的不同,设计模式存在的意义就是设计出富有弹性的系统,应用工厂方法模式是为了在扩展产品类别的时候程序富有弹性,而抽象工厂模式的设计则是在扩展产品家族的时候更方便,记住这个区别就不会混淆了。

本文围绕抽象工厂模式展开,对比简单工厂和工厂方法,指出抽象工厂适合对现有产品细分。以菜单为例介绍程序实现,分析其扩展情况,总结抽象工厂模式的定义、应用场景、优缺点及角色组成,还强调与工厂方法模式的设计目的区别。

被折叠的 条评论
为什么被折叠?



