模拟场景:在上次的工厂设计模式中,女娲造了一群人。后面觉得不合适,世界上的人都好像傀儡,没有任何感情。所以她打算重新造人,让人类有性别之分:男、女。但是女娲不可能全部推倒重做吧,这个时候就要进行旧物回收利用了。
在这里我们先进行分析一下,首先是human这个类,因为这里涉及到了sex、color、doSomething三个方法,很明显这些方法要定义到human这个接口中,具体是什么sex、什么color都是由子类去实现。那么就肯定有Yellow、White、Black三种不同肤色的human,所以要创建YellowHuman、WhiteHuman、BlackHuman三个类,但是考虑下,实现了Human接口,是否意味着要把这三个接口全部都实现呢?(下面只以YellowHuman为例进行说明,其他两个是一样的)
其实不是,因为分析一下就知道,这里涉及到sex,那么femaleYellowHuman和maleYellowHuman只是sex不同而已,其他的像color和doSomething的操作时一样的。所以这个时候YellowHuman不能定义成普通的类,因为如果是普通的类的话就需要实现接口的全部方法。那么我们就可以使用abstract类了。不要忘记了,抽象类中是可以存在非抽象方法的,所以把共有的方法或者属性写到抽象类中,不实现getSex()方法即可。至于具体操作交给子类去实现即可。
接下来是工厂factory。工厂的操作就简单多了,在这里,虽然要创建不同肤色不同性别的human,都是会发现,其实需要创建两个factory,那就是以性别来区分(FemaleHumanFactory、MaleHumanFactory),因为我们生成的human中,最后是生成FemaleXXXHuman、MaleXXXHuman。
如下代码:(也是以YellowHuman为例,其他操作类似)
Human:
1 package com.zqz.dp.abstractfactory.human; 2 /** 3 * @author Qin 定义human的接口,human都有一些相同的属性,如人都有肤色、性别等等 4 */ 5 public interface Human { 6 public void getColor(); // human的肤色 7 public void getSex(); // human的性别 8 public void doSomething(); // human可以做事 9 }
AbstractYellowHuman:
1 package com.zqz.dp.abstractfactory.human; 2 /** 3 * @author Qin 4 * 定义一个黄种人的抽象类,所有的黄种人有着相同的肤色,可以做一样的事情,不同的只是有性别之分而已 5 * 所以此抽象类来定义相同的属性 6 */ 7 public abstract class AbstractYellowHuman implements Human { 8 @Override 9 public void getColor() { 10 System.out.println("黄种人的肤色是黄色的。。。"); 11 } 12 @Override 13 public void doSomething() { 14 System.out.println("我是黄种人。。。"); 15 } 16 }
FemaleYellowHuman:
1 package com.zqz.dp.abstractfactory.human; 2 /** 3 * @author Qin 4 * 定义女性黄种人,只需要覆写其中的性别即可,黄种人除了性别有着其他的共有属性 5 */ 6 public class FemaleYellowHuman extends AbstractYellowHuman { 7 @Override 8 public void getSex() { 9 System.out.println("我是女黄种人。。。"); 10 } 11 }
MaleYellowHuman:
1 package com.zqz.dp.abstractfactory.human; 2 /** 3 * @author Qin 4 * 定义男性黄种人,只需要覆写其中的性别即可,黄种人除了性别有着其他的共有属性 5 */ 6 public class MaleYellowHuman extends AbstractYellowHuman { 7 @Override 8 public void getSex() { 9 System.out.println("我是男黄种人。。。"); 10 } 11 }
HumanFactory:
1 package com.zqz.dp.abstractfactory.factory; 2 import com.zqz.dp.abstractfactory.human.Human; 3 /** 4 * @author Qin 5 * human工厂,用来创建不同肤色的human,下面定义了三个肤色,具体生成的是female还是mela交给子类去实现 6 */ 7 public interface HumanFactory { 8 public Human createYellowHuman(); // 生成黄种人的实现 9 public Human createWhiteHuman(); // 生成白种人的实现 10 public Human createBlackHuman(); // 生成黑种人的实现 11 }
FemaleHumanFactory:
1 package com.zqz.dp.abstractfactory.factory; 2 import com.zqz.dp.abstractfactory.human.AbstractBlackHuman; 3 import com.zqz.dp.abstractfactory.human.AbstractWhiteHuman; 4 import com.zqz.dp.abstractfactory.human.AbstractYellowHuman; 5 import com.zqz.dp.abstractfactory.human.FemaleBlackHuman; 6 import com.zqz.dp.abstractfactory.human.FemaleWhiteHuman; 7 import com.zqz.dp.abstractfactory.human.FemaleYellowHuman; 8 /** 9 * @author Qin 创建不同肤色,但是性别为female(女)的human 10 */ 11 public class FemaleHumanFactory implements HumanFactory { 12 @Override 13 public AbstractYellowHuman createYellowHuman() {// 返回黄种人对象 14 return new FemaleYellowHuman(); // 生成女性黄种人 15 } 16 @Override 17 public AbstractWhiteHuman createWhiteHuman() {// 返回白种人对象 18 return new FemaleWhiteHuman(); // 生成女性白种人 19 } 20 @Override 21 public AbstractBlackHuman createBlackHuman() {// 返回黑种人对象 22 return new FemaleBlackHuman(); // 生成女性黑种人 23 } 24 }
MaleHumanFactory:
1 package com.zqz.dp.abstractfactory.factory; 2 import com.zqz.dp.abstractfactory.human.AbstractBlackHuman; 3 import com.zqz.dp.abstractfactory.human.AbstractWhiteHuman; 4 import com.zqz.dp.abstractfactory.human.AbstractYellowHuman; 5 import com.zqz.dp.abstractfactory.human.MaleBlackHuman; 6 import com.zqz.dp.abstractfactory.human.MaleWhiteHuman; 7 import com.zqz.dp.abstractfactory.human.MaleYellowHuman; 8 /** 9 * @author Qin 创建不同肤色,但是性别为male(男)的human 10 */ 11 public class MaleHumanFactory implements HumanFactory { 12 @Override 13 public AbstractYellowHuman createYellowHuman() { //返回黄种人对象 14 return new MaleYellowHuman(); // 生成男性黄种人 15 } 16 @Override 17 public AbstractWhiteHuman createWhiteHuman() { //返回白种人对象 18 return new MaleWhiteHuman(); // 生成男性白种人 19 } 20 @Override 21 public AbstractBlackHuman createBlackHuman() { //返回黑种人对象 22 return new MaleBlackHuman(); // 生成男性黑种人 23 } 24 }
NvWa:
1 package com.zqz.dp.abstractfactory.client; 2 import com.zqz.dp.abstractfactory.factory.FemaleHumanFactory; 3 import com.zqz.dp.abstractfactory.factory.HumanFactory; 4 import com.zqz.dp.abstractfactory.factory.MaleHumanFactory; 5 import com.zqz.dp.abstractfactory.human.Human; 6 /** 7 * @author Qin NvWa类,开始生产不同性别的人类 8 */ 9 public class NvWa { 10 public static void main(String[] args) { 11 create(); 12 } 13 public static void create() { 14 /** 15 * 创建两个工厂,生成female、male的human 16 */ 17 HumanFactory femaleFactory = new FemaleHumanFactory(); // 生成female的human工厂 18 HumanFactory maleFactory = new MaleHumanFactory(); // 生成male的human工厂 19 /** 20 * 开始创建不同sex、不同肤色的human 21 */ 22 Human femaleYellowHuman = femaleFactory.createYellowHuman(); //创建female黄种人 23 Human maleYellowHuman = maleFactory.createYellowHuman(); //创建male黄种人 24 femaleYellowHuman.getSex(); //取得female黄种人的性别 25 maleYellowHuman.getSex(); //取得male黄种人的性别 26 /** 27 * 生成其他肤色的human、一样的操作,略去 28 */ 29 } 30 }
抽象工厂的定义:未创建一组相关或者相互依赖的对象提供一个接口,而且无需指定它们的具体类。
抽象工厂的优点:
封装性,每个产品的实现类其他模块不需要关心,关系的只是工厂类是哪个,只要知道工厂类是哪个,我就可以创建出一些需要的对象。
抽象工厂的缺点:
横向扩展方便,即如果我们要定义一个中性的human、扩展是很方便的。只是纵向扩展很麻烦。如果要再创建一种其他肤色的human时。
抽象工厂的使用场景:
抽象工厂定义了一系列的产品,如果想对这一系列的产品进行拓展,或者想要替换掉一系列的产品,生成新的系列操作,或者控制系列产品的生产过程,那么就用抽象工厂。
一个对象族(或者一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂。