n
抽象工厂(Abstract Factory)
模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式的简略类图
如下:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/cx.jpg)
左边的等级结构代表工厂的等级结构,右边的两个等级结构分别代表两个不同的产品的等级结构。
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多
个产品族中的产品对象。这就是抽象工厂模式的用意。
好,在让我们以农场的例子来进行一次分析,现在又有了新的需求,农场中不只种植水果现在农场的业务得到了
扩展需要种植蔬菜
(Veggie)
了
,
而且农场需要按照地理位置来区分水果和蔬菜。
因此在系统中产品的分成了两个等级结构:水果
(Fruit)
和蔬菜
(Veggie)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/图片2.jpg)
看下图:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/tp3.jpg)
可以看出,这个系统的产品可以分成两个等级结构:Fruit和Veggie,以及两个产品族:
Tropical(热带)
,
Northern
(北方)
现在我们已经对新的需求进行了深入的分析,那么下面就让我们来看看要如何实现需求。
首先对应面向对象设计来讲,一般是需要先抽象出类的共通行为和特性。那么在我们的系统中具有两个抽象
点,第一个是产品:也就是水果和蔬菜。第二个是产品族:也就是按照地理位置进行的划分区。
对于第一抽象点来说:把水果和蔬菜进行抽象化,得到下面的
UML
图
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/图片4.jpg)
对于第二抽象点:是按照产品族来划分,
Tropical
中包含了两个产品
(Fruit
和
Veggie)
Northem
中也包含了两个产品
(Fruit
和
Veggie)
,而根据需求产品族应该由园丁
(Gardener)
来管理
.
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/图片5.jpg)
与抽象工厂模式的各个角色相对照,不难发现,所谓各个园丁其实就是各个工厂角色,而水果和蔬菜角色则是产
品角色。将抽象工厂模式应用于农场系统中,设计
UML
如下:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/wangqun2007/图片6.jpg)
Gardener接口代码清单:
public interface Gardener{
public Fruit createFruit(String name);
public Veggie createVeggie(String name);
}
具体工厂类NorthernGardener的代码清单
public class NorthernGardener implements Gardener{
public Fruit createFruit(String name){
return new NorthernFruit(name);
}
public Veggie createVeggie(String name){
return new NorthernVeggie(name);
}
}
具体工厂类
TropicalGardener
的代码清单
public class TropicalGardener implements Gardener{
public Fruit createFruit(String name){
return new TropicalFruit(name);
}
public Veggie createVeggie(String name){
return new TropicalVeggie(name);
}
}
抽象工厂的使用:
Gardener gardener=new NorthernGardener();
Fruit appleFruit=gardener.createFruit("apple");
Veggie cabbageVeggie=gardener.createVeggie("cabbage");
Gardener gardener2=new TropicalGardener();
Fruit strawberryFruit=gardener2.createFruit("strawberry");
Veggie wangdouVeggie=gardener2.createVeggie("wangdou");
到这里大家可能有一个疑问上面的抽象工厂好像和工厂方法没什么大的区别,就是比工厂方法多了一个方法函数
而已吗。对于这个问题需要从设计的角度去分析,工厂方法可以用来处理同种类产品的创建,而如何解决以
产品族为界线划分的产品的创建呢,我们需要对工厂方法进行再次的抽象,而抽象的重心则放到了族的概念
上这样修改后的工厂方法我们就称之为抽象工厂。
在这里我们又遇到了工厂方法中遇到的问题,抽象工厂的接口类和具体实现类在使用的时候又是通过
了new的方式直接引用的,那么下面我们来解决这个问题。
修改Gardener使其成为一个abstract class
public abstract class AbsGardenerFactory {
public static AbsGardenerFactory createFactory(Request req) {
String absFactoryName= req.getAttribute("absfactory");
if(absFactoryName.equals("northern")){
return new NorthernGardener2();
}
if(absFactoryName.equals("tropical")){
return new TropicalGardener2();
}
return null;
}
public abstract Fruit createFruit(String name);
public abstract Veggie createVeggie(String name);
}
这样根据上面的代码我们的客户端程序可以是这样的
Request req = new Request();
req.setAttribute("absfactory", "northern");
AbsGardenerFactory gardener = AbsGardenerFactory.createFactory(req);
Fruit appleFruit = gardener.createFruit("apple");
Veggie cabbageVeggie = gardener.createVeggie("cabbage");
Request req2 = new Request();
req2.setAttribute("absfactory", "tropical");
AbsGardenerFactory gardener2 = AbsGardenerFactory.createFactory(req2);
Fruit strawberryFruit = gardener2.createFruit("strawberry");
Veggie wangdouVeggie = gardener2.createVeggie("wangdou");
这样我们的客户端代码只和抽象工厂类打交道,而充分的进行了解耦合。
开闭原则:
对于产品族来说在产品的等级结构不发生变化时,如果我们想新增一个产品族那么我们只需要在实现
一个新的具体工厂即可。这符合开闭原则。
当产品等级结构发生变化时,由于抽象工厂是以族来划分的,也就是说抽象工厂在设计阶段就已经定
义好了族中的产品等级结构,而现在我们如果想添加新的产品等级结构时,势必要修改抽象工厂的定义。所
有不符合开闭原则。