初学编程模式,请读者指出不正确指出,多谢!
抽象工厂模式的作用是为了灵活地生产产品。如果产品能够从一维的角度进行分类的话,可以直接使用普通的工厂模式即可。但是,在真实环境下,产品的属性可能是二维或者更高维的,所以这个时候就要用到抽象工厂了。本文完全参考CBF4LIFE缩写的《Java设计模式》,网上可下,文中的抽象工厂使用了女娲补天,不是,是女娲造人的例子来阐明抽象工厂模式,诙谐生动。在这里,我就借助这个例子来描述本人对抽象工厂的理解。
首先,把人看作产品,那么人首先有肤色之分:白,黑,黄;同时也有性别之分:男,女;这两种属性是交叉存在的,也就是说既有黄色的男人,也有白色的女人等等。如果使用普通工厂的思路来考虑的话,直接在单一的工厂里设计六个方法,分别生产需要的人种即可。但是,这样太麻烦了。而且灵活度很低,对于我们这里的需求,先定义抽象工厂的基本功能就是生产三个颜色的人种,不分男女,即,工厂的基本方法就有:生产黄人,黑人,白人。然后,在定义两种具体的工厂,男人工厂,女人工厂。这样,通过调用男人工厂的三个函数可以生产黑男人,白男人和黄男人;调用女人工厂可以生产黑女人,白女人和黄女人。这样,能够灵活地生产这几个人种了。
有人可能疑问,为什么不设计三个工厂:黑人工厂,白人工厂,黄人工厂?这样当然也是可以的,只是从另一个角度来决定工厂的作用,这种情况下,工厂的基本功能就是生产男人和女人了。
整理的程序结构如下(摘抄至《java设计模式》):
1、定义接口(interface)Human,包含了所有人的全部特征

package com.cbf4life; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 定义一个人类的统称,问题出来了,刚刚定义的时候忘记定义性别了 这个重要的问题非修改不可,否则这个世界上太多太多的东西不存在了 */ public interface Human { // 首先定义什么是人类 // 人是愉快的,会笑的,本来是想用smile表示,想了一下laugh更合适,好长时间没有大笑了; public void laugh(); // 人类还会哭,代表痛苦 public void cry(); // 人类会说话 public void talk(); // 定义性别 public void sex(); }
2、定义了人所有种类的枚举变量HumanEnum,共六种变量,在通过工厂创建产品的时候,工厂通常需要将创建的产品的类名传入,生成类的实例。用枚举变量可以很好地保存六种产品类(就是这里的人种)的名称,这个技巧非常值得学习

package com.cbf4life; public enum HumanEnum { // 把世界上所有人类型都定义出来 YelloMaleHuman("com.cbf4life.yellowHuman.YellowMaleHuman"), YelloFemaleHuman( "com.cbf4life.yellowHuman.YellowFemaleHuman"), WhiteFemaleHuman( "com.cbf4life.whiteHuman.WhiteFemaleHuman"), WhiteMaleHuman( "com.cbf4life.whiteHuman.WhiteMaleHuman"), BlackFemaleHuman( "com.cbf4life.blackHuman.BlackFemaleHuman"), BlackMaleHuman( "com.cbf4life.blackHuman.BlackMaleHuman"); private String value = ""; // 定义构造函数,目的是Data(value)类型的相匹配 private HumanEnum(String value) { this.value = value; } public String getValue() { return this.value; } }
3、接下来,需要定义一个工厂的接口,这个接口中包含了所有基本的工厂操作,也就是上文提到的生产黄人,黑人,白人的三个方法

package com.cbf4life; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 这次定一个接口,应该要造不同性别的人,需要不同的生产线 那这个八卦炉必须可以制造男人和女人 */ public interface HumanFactory { // 制造黄色人种 public Human createYellowHuman(); // 制造一个白色人种 public Human createWhiteHuman(); // 制造一个黑色人种 public Human createBlackHuman(); }
4、然后定义造人工厂的抽象类,该抽象类的作用自然就是造人了,它只负责根据传入的类的名称造人,管你造男人女人黑人白人

package com.cbf4life.humanFactory; import com.cbf4life.Human; import com.cbf4life.HumanEnum; import com.cbf4life.HumanFactory; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 编写一个抽象类,根据enum创建一个人类出来 */ public abstract class AbstractHumanFactory implements HumanFactory { /* * 给定一个性别人种,创建一个人类出来专业术语是产生产品等级 */ protected Human createHuman(HumanEnum humanEnum) { Human human = null; // 如果传递进来不是一个Enum中具体的一个Element的话,则不处理 if (!humanEnum.getValue().equals("")) { try { // 直接产生一个实例 human = (Human) Class.forName(humanEnum.getValue()) .newInstance(); } catch (Exception e) { // 因为使用了enum,这个种异常情况不会产生了,除非你的enum有问题; e.printStackTrace(); } } return human; } }
5、在抽象类工厂类额基础上,就是具体的工厂类了,分为男人类MaleHumanFactory和女人类FemaleHumanFactory,每个类中的具体方法也要对应体现

package com.cbf4life.humanFactory; import com.cbf4life.Human; import com.cbf4life.HumanEnum; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 女性创建工厂 */ public class FemaleHumanFactory extends AbstractHumanFactory { // 创建一个女性黑种人 public Human createBlackHuman() { return super.createHuman(HumanEnum.BlackFemaleHuman); } // 创建一个女性白种人 public Human createWhiteHuman() { return super.createHuman(HumanEnum.WhiteFemaleHuman); } // 创建一个女性黄种人 public Human createYellowHuman() { return super.createHuman(HumanEnum.YelloFemaleHuman); } }

package com.cbf4life.humanFactory; import com.cbf4life.Human; import com.cbf4life.HumanEnum; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 男性创建工厂 */ public class MaleHumanFactory extends AbstractHumanFactory { // 创建一个男性黑种人 public Human createBlackHuman() { return super.createHuman(HumanEnum.BlackMaleHuman); } // 创建一个男性白种人 public Human createWhiteHuman() { return super.createHuman(HumanEnum.WhiteMaleHuman); } // 创建一个男性黄种人 public Human createYellowHuman() { return super.createHuman(HumanEnum.YelloMaleHuman); } }
不好意思把女人类放在前面了,谁让现在男人没地位呢。
6、接下来,就是各个产品(人)的具体情况了
首先定义黑人的抽象类AbstractBlackHuman,以及具体类,黑男人BlackMaleHuman(应该说男黑人,意思都差不多),黑女人(听起来很别扭)BlackFemaleHuman

package com.cbf4life.blackHuman; import com.cbf4life.Human; public abstract class AbstractBlackHuman implements Human { public void cry() { System.out.println("黑人会哭"); } public void laugh() { System.out.println("黑人会笑"); } public void talk() { System.out.println("黑人可以说话,一般人听不懂"); } }

package com.cbf4life.blackHuman; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 女性黑种人 */ public class BlackFemaleHuman extends AbstractBlackHuman { public void sex() { System.out.println("该黑种人的性别为女..."); } }

package com.cbf4life.blackHuman; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 男性黑种人 */ public class BlackMaleHuman extends AbstractBlackHuman { public void sex() { System.out.println("该黑种人的性别为男..."); } }
然后是黄人

package com.cbf4life.yellowHuman; import com.cbf4life.Human; public abstract class AbstractYellowHuman implements Human { public void cry() { System.out.println("黄色人种会哭"); } public void laugh() { System.out.println("黄色人种会大笑,幸福呀!"); } public void talk() { System.out.println("黄色人种会说话,一般说的都是双字节"); } }

package com.cbf4life.yellowHuman; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 女性黄种人 */ public class YellowFemaleHuman extends AbstractYellowHuman { public void sex() { System.out.println("该黄种人的性别为女..."); } }

package com.cbf4life.yellowHuman; /** * @author cbf4Life cbf4life@126.com * I'm glad to share my knowledge with you all. * 男性黄种人 */ public class YellowMaleHuman extends AbstractYellowHuman { public void sex() { System.out.println("该黄种人的性别为男...."); } }
最后是白人

package com.cbf4life.whiteHuman; import com.cbf4life.Human; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 白色人人种 为了代码整洁,新建一个包,这里是白种人的天下了 */ public abstract class AbstractWhiteHuman implements Human { public void cry() { System.out.println("白色人种会哭"); } public void laugh() { System.out.println("白色人种会大笑,侵略的笑声"); } public void talk() { System.out.println("白色人种会说话,一般都是但是单字节!"); } }

package com.cbf4life.whiteHuman; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 女性白种人 */ public class WhiteFemaleHuman extends AbstractWhiteHuman { public void sex() { System.out.println("该白种人的性别为女...."); } }

package com.cbf4life.whiteHuman; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 男性白种人 */ public class WhiteMaleHuman extends AbstractWhiteHuman { public void sex() { System.out.println("该白种人的性别为男...."); } }
7,任何工厂都定义好了,女娲娘娘,可以开始了!(!要叫我女王大人!)

package com.cbf4life; import com.cbf4life.humanFactory.FemaleHumanFactory; import com.cbf4life.humanFactory.MaleHumanFactory; public class NvWa { public static void main(String[] args) { // 第一条生产线,男性生产线 HumanFactory maleHumanFactory = new MaleHumanFactory(); // 第二条生产线,女性生产线 HumanFactory femaleHumanFactory = new FemaleHumanFactory(); // 生产线建立完毕,开始生产人了: Human maleYellowHuman = maleHumanFactory.createYellowHuman(); Human femaleYellowHuman = femaleHumanFactory.createYellowHuman(); maleYellowHuman.cry(); maleYellowHuman.laugh(); femaleYellowHuman.sex(); /* * ..... 后面你可以续了 */ } }
以上便是本人对抽象工厂的理解,所有代码全部盗版CBF4LIFE的《Java设计模式》。如有错误或者不妥,欢迎留言。