抽象工厂模式的定义
为创建一组相关的或相互依赖的对象提供一个接口,而且无需指定他们的具体类
抽象工厂模式的通用类图
抽象工厂模式是工厂方法模式的升级产品,在有多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
抽象工厂模式通用源代码类图
首先由两个互相影响的产品线(也叫产品族),例如制造汽车的左侧车门和右侧车门,这两个应该是数量相等的----两个对象间的约束,每个型号的车门是不一样的,这是产品等级的结构约束。 下面看下源码实现:
抽象产品类A
package com.zxf.srp.factory3;
public abstract class AbstractProductA {
//每个产品都公有的方法
public void shardMethod(){}
//没个产品相同方法,不同的实现
public abstract void doSomething();
}
产品A1的实现
public class ProductA1 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品A1的实现方法");
}
}
产品A2的实现
public class ProductA2 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品A2的实现方法");
}
}
抽象产品类B
public abstract class AbstractProductB {
//每个产品都公有的方法
public void shardMethod(){}
//没个产品相同方法,不同的实现
public abstract void doSomething();
}
产品B1的实现
public class ProductB1 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("产品B1的实现方法");
}
}
产品B2的实现
public class ProductB2 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("产品B2的实现方法");
}
}
抽象工厂类的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂定义了两个产品族的产品创建。
抽象工厂类
public abstract class AbstractCreator {
//创建A产品家族
public abstract AbstractProductA createProductA();
//创建B产品家族
public abstract AbstractProductB createProductB();
}
如何创建一个产品,则是由具体的实现类来完成的。
产品等级1的实现类
public class Creator1 extends AbstractCreator {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
产品等级2的实现类
public class Creator1 extends AbstractCreator {
@Override
public AbstractProductA createProductA() {
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ProductB2();
}
}
注意:有M个产品等级就应该有M个实现类工厂,在每个实现工厂中。实现不同产品组的生产任务
场景类
public class Client {
public static void main(String[] args){
//定义出两个工厂
AbstractCreator creator1 = new Creator1();
AbstractCreator creator2 = new Creator2();
//产生1级对象
AbstractProductA productA1 = creator1.createProductA();
AbstractProductB productB1 = creator1.createProductB();
//产生2级对象
AbstractProductA productA2 = creator1.createProductA();
AbstractProductB productB2 = creator1.createProductB();
}
}
在场景类类中,没有一个方法与实现类有关系,对于一个产品来说,我们只要知道它的工厂方法就可以直接产生一个产品对象,无需关心他的实现类。
具体的实例
我们改造之前的女娲的例子,女娲造人需要区分男女。下面是类图:
这个类图虽然大,但是比较简单,一个接口,多个抽象类,然后是N个实现类,每一个人中都是抽象类,性别是在个各自的实现类中实现的,HumanFactory接口中定义了三个方法,别分用来生产三个不同肤色的人中。
代码示例如下:
/**
* 人类接口
*/
public interface Human {
/**
* 不同的肤色
*/
public void getColor();
/**
* 不同的语言
*/
public void getLanguage();
/**
* 不同的性别
*/
public void getSex();
}
/**
* 白种人
*/
public abstract class AbstractWhiteHuman implements Human {
@Override
public void getColor() {
System.out.println("白种人皮肤是白色的");
}
@Override
public void getLanguage() {
System.out.println("白种人说英语");
}
}
/**
* 黑种人
*/
public abstract class AbstractBlackHuman implements Human {
@Override
public void getColor() {
System.out.println("黑种人皮肤是黑色的");
}
@Override
public void getLanguage() {
System.out.println("黑种人说南非语");
}
}
/**
* 黄种人
*/
public abstract class AbstractYellowHuman implements Human {
@Override
public void getColor() {
System.out.println("黄种人皮肤是黄色的");
}
@Override
public void getLanguage() {
System.out.println("黄种人说汉语");
}
}
每个抽象类都有两个实现类,分别实现公共的最细节,最具体的事物。
/**
* 黄种人女性
*/
public class FemaleYellowHuman extends AbstractYellowHuman {
@Override
public void getSex() {
System.out.println("黄种人女性");
}
}
/**
* 黄种人男性
*/
public class MaleYellowHuman extends AbstractYellowHuman {
@Override
public void getSex() {
System.out.println("黄种人男性");
}
}
白种人和黑种人的具体实现跟黄种人一样,就省略了。
/**
* 人类创建工厂类
*/
public interface HumanFactory {
//制造一个黄种人
public Human createYellowHuman();
//制造一个白种人
public Human createWhiteHuman();
//制造一个黑种人
public Human createBlackHuman();
}
在接口中,我们是可以生产出不同肤色人种的,具体生产那种性别的人,需要下面去具体工厂去实现。
/**
* 女性制造工厂
*/
public class FemaleFactory implements HumanFactory {
//创建黄种人女性
@Override
public Human createYellowHuman() {
return new FemaleYellowHuman();
}
//创建白种人女性
@Override
public Human createWhiteHuman() {
return new FemaleWhiteHuman();
}
//创建黑种人女性
@Override
public Human createBlackHuman() {
return new FemaleBlackHuman();
}
}
/**
* 男性制造工厂
*/
public class MaleFactory implements HumanFactory {
//创建黄种人男性
@Override
public Human createYellowHuman() {
return new MaleYellowHuman();
}
//创建白种人男性
@Override
public Human createWhiteHuman() {
return new MaleWhiteHuman();
}
//创建黑种人男性
@Override
public Human createBlackHuman() {
return new MaleBlackHuman();
}
}
/**
* 场景类
*/
public class NvWa {
public static void main(String[] args){
//第一条生产线
HumanFactory maleFactory = new MaleFactory();
//第二条生产线
HumanFactory femaleFactory = new FemaleFactory();
//生产线建立完毕,开始生产人
Human yellowMaleHuman = maleFactory.createYellowHuman();
Human yellowFemaleHuman = femaleFactory.createYellowHuman();
System.out.println("----生产一个黄种人女性-----");
yellowFemaleHuman.getColor();
yellowFemaleHuman.getLanguage();
yellowFemaleHuman.getSex();
System.out.println("----生产一个黄种人男性-----");
yellowMaleHuman.getColor();
yellowMaleHuman.getLanguage();
yellowMaleHuman.getSex();
}
}
结果:
----生产一个黄种人女性-----
黄种人皮肤是黄色的
黄种人说汉语
黄种人女性
----生产一个黄种人男性-----
黄种人皮肤是黄色的
黄种人说汉语
黄种人男性
各种肤色的男性和女性都制造出来了,男性制造工厂只生产男性,女性制造工厂只生成女性,以后增加性别就很简单了,在创建一个工厂生产就行了。
抽象工厂的应用
抽象工厂模式的有点
1.封装性,每个产品的实现类不是高层模块要关心的,它关心的是接口,是抽象。对象是由工厂类制造出来的,我们只要知道工厂类是谁,就能创造出一个需要的对象。 2.产品族内的约束为非公开状态。例如生产男女比例的问题上,就应该有这样一个约束,每生产一个女性,就生产出一个男性,这样的生产过程对调用工厂的高层模块来说是透明的,他不需要知道这个约束。
抽象工厂模式的缺点
1.抽象工厂模式的最大缺点是产品族扩展非常困难,我们以通用代码为例,如果要增加一个产品C,也就是产品家族由原来的2个增加到3个,抽象类AbstractCreatoryao 增加一个方法,createProductC(),然后两个实现类都要修改,这严重违反了开闭原则。
抽象工厂的使用场景
抽象工厂模式的使用场景非常简单,一个对象族都有相同的约束,则可以使用抽象工厂模式,
抽象工厂的注意事项
抽象工厂模式的扩展比较困难,但是一定要清楚,是扩展产品族困难,而不是扩展产品等级困难,以上面的例子来说,增加一个肤色和困难,而增加一个性别很简单。
特别感谢
《设计模式之禅》
PS:觉得文章不还错的话可以添加公众号关注下,文章都会同步到公众号。