工厂模式三部曲的最后一部就是抽象工厂模式,首先比较一下三种模式的UML图:
1.简单工厂模式
2.工厂方法模式
工厂方法简略图
3.抽象工厂模式
抽象工厂模式简略图
这三个图的右边都是具体产品,左边都是工厂类。从上下三个图中可以看出,抽象工厂模式右边是2个以上的产品对象,也就是可以说是一个产品族。这就是抽象工厂模式最大的不同就是针对一个产品族。
所谓产品族:就是指位于不同产品等级结构中,功能相关联的产品组成的家族,举个简单的例子,南方的橘子和北方的橘子都属于一个橘子族。中国人和美国人虽属于不同国家的人,但他们也属于一个族就是人族。我认为使用相图可以很好的理解产品族:
这里打个比方就是,第一层的四个不同的图标代表美国人、日本人、法国人、中国人的话,他们都属于一个产品族就是人族。
在认识了产品族的基础上,现在说一下什么叫抽象工厂模式:抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的,抽象工厂模式可以向客户端提供一个接口,使得客户端在不必置顶产品的具体类型的情况下能够创建多个产品族的产品对象
1.抽象工厂模式中的角色和职责
。抽象工厂角色(Creator)
抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口
。 具体工厂角色(Concrete Creator)
具体工厂类是抽象工厂类的一个实现,负责实例化某个产品族的产品对象
。抽象角色(product)
抽象模式所创建的所有对象的父类,它描述所有实例所共有的公共接口
。 具体产品角色(Concfrete Product)
抽象模式岁创建的具体实例对象
下面我还用华苑长华里的菜市场里面的买菜的,一个卖菜的摊主就是一个工厂角色,他卖很多种的菜,比如菜有以下三种:
1.白菜: 白菜现在开始分为:宝坻白菜和静海白菜
2.黄瓜: 黄瓜现在分为:宝坻黄瓜和静海黄瓜
3.西红柿: 西红柿现在也分为:宝坻西红柿和静海西红柿
这样的话,该蔬菜结构就有两个产品族:宝坻蔬菜和静海蔬菜。 这些蔬菜都有一些共同的属性,即 进货时间,产地,价钱,这样就可以建立一个蔬菜的接口,使用UML图描述如下:
蔬菜接口:有如下方法:getPurchaseDate()//获取进货日期,getOrigin()//获取蔬菜产地,getPrice()//获取价格。
使用代码清单就是:
public interface Vegetable{
/*
*获取进货日期
*
*/
public void getPurchaseDate();
/*
*获取产地
*
*/
public void getOrigin();
/*
*获取蔬菜价格
*
*/
public void getPrice();
}
接着是三个具体蔬菜类:
白菜抽象角色蔬菜角色:
public abstrct class Cabbage implements Vegetable {
/*
*获取进货日期
*
*/
public abstrct void getPurchaseDate();
/*
*获取产地
*
*/
public abstrct void getOrigin();
/*
*获取蔬菜价格
*
*/
public abstrct void getPrice();
}
宝坻白菜具体类
public class BaoDiCabbage extends Cabbage{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-25”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津宝坻”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“1.00元/千克”);
}
}
静海白菜具体类
public class JingHaiCabbage extends Cabbage{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-24”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津静海”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“2.00元/千克”);
}
}
黄瓜的抽象类就是
public abstrct class Cucumber implements Vegetable {
/*
*获取进货日期
*
*/
public abstrct void getPurchaseDate();
/*
*获取产地
*
*/
public abstrct void getOrigin();
/*
*获取蔬菜价格
*
*/
public abstract void getPrice();
}
宝坻黄瓜具体类
public class BaoDiCucumber extends Cucumber{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-26”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津宝坻”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“5.00元/千克”);
}
}
静海黄瓜具体类
public class JingHaiCucumber extends Cucumber{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-26”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津静海”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“5.00元/千克”);
}
}
西红柿的抽象类就是:
public abstract class Tomatoes implements Vegetable {
/*
*获取进货日期
*
*/
public void getPurchaseDate();
/*
*获取产地
*
*/
public void getOrigin();
/*
*获取蔬菜价格
*
*/
public void getPrice();
}
宝坻西红柿的实体类就是:
public class BaoDiTomatoes extends Tomatoes{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-23”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津宝坻”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“6.00元/千克”);
}
}
静海西红柿的实体类就是:
public class JingHaiTomatoes extends Tomatoes{
/*
*获取进货日期
*
*/
public void getPurchaseDate(){
System.out.println(“2009-7-23”);
}
/*
*获取产地
*
*/
public void getOrigin(){
System.outprintln(“天津静海”);
}
/*
*获取蔬菜价格
*
*/
public void getPrice(){
System.out.println(“6.00元/千克”);
}
}
工厂接口类VegetableFactory
public interface VegetableFactory{
//实例化白菜
public Vegetable getCabbage();
//实例化黄瓜
public Vegetable getCucumber();
//实例化西红柿
public Vegetable getTomatoes();
}
静海蔬菜工厂实例化类:
public class JingHaiVegetableFactory implements VegetableFactory{
//实例化白菜
public Vegetable getCabbage(){
return (Vegetable) new JingHaiCabbage();
}
//实例化黄瓜
public Vegetable getCucumber(){
return (Vegetable) new JingHaiCucumber();
}
//实例化西红柿
public Vegetable getTomatoes(){
return (Vegetable) new JinghaiTomatoes();
}
}
宝坻蔬菜工厂实例化类:
public class BaoDiVegetableFactory implements VegetableFactory{
//实例化白菜
public Vegetable getCabbage(){
return (Vegetable) new BaoDiCabbage();
}
//实例化黄瓜
public Vegetable getCucumber(){
return (Vegetable) new BaoDiCucumber();
}
//实例化西红柿
public Vegetable getTomatoes(){
return (Vegetable) new BaoDiTomatoes();
}
}
客户端测试类
public class MainClass{
public static void main(String[] agrs){
//Vegetable cabbage = VegetableFactory.factory(“Cabbage”);
// Vegetable tomatoes = VegetableFactory.factory(“Tomatoes”);
// cabbage.getPrice();
// tomatoes.getPrice();
//上面是一般工厂模式的测试程序
//VegetableFactory cabbageFactory = new CabbageFactory();
//Vegetable vegetable = cabbageFactory.getVegetableObject();
//vegetable.getPrice();
//VegetableFactory tomatoesFactory = new TomatoesFactory();
//vegetable = tomatoesFactory.getVegetableObject();
//vegetable.getPrice();
//上面是工厂方法模式
VegetableFactory vegetableFactory = new JingHaiVegetableFactory();
Vegetable jinghaiCabbage = vegetableFactory.getCabbage();
jinghaiCabbage.getPrice();
VegetableFactory vegetableFactory2 = new BaoDiVegetableFactory();
Vegetable baodiTomatoes = vegetableFactory2.getTomatoes();
baodiTomatoes .getPrice();
}
}
通过以上的一点点走下来,自己更明白抽象工厂模式了,也发现了在一般工厂模式和工厂方法模式里面的UML图很多地方都画错了,这里的UML图也是修改了又修改,我一直感觉抽象工厂模式很复杂,现在理解了也好多了。具体在什么情形下使用抽象工厂模式呢,从【java与设计模式】中看到是这样的
。一个系统不应当以来与产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
。这个系统的产品有多余一个的产品类,而系统只消费其中某一族的产品(抽象工厂模式的原始用意)
。同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来
。系统提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于实现
到现在为止,三个工厂模式已经结束了,工厂模式是JAVA各个框架使用最为广泛的设计模式,也是JAVA API使用最为广泛的模式。把window系统的组件看称一个产品族,把mac系统的组件看作一个产品族,把linux系统组件看作一个产品族,使用抽象工厂模式实现了JAVA的跨平台,真的很有意思,虽说不全是如此。