设计模式(三)之抽象工厂模式
前言
上一节学习到了工厂方法模式,工厂方法模式也有几个扩展。
1.简单工厂模式
2.多个工厂的工厂方法模式
回顾一下,上一节的内容:
什么是简单工厂模式?
简单工厂模式包含一个工厂类,使用静态方法创建对象,因为只有一个工厂类,所以减少了工厂类的接口或抽象类,直接使用静态方法创建所有实现了产品接口的产品类对象。
对于简单工厂模式,当需要增加一个产品,只需要实现了产品类的接口,而不需要改变其他任何代码就可以完成产品类的新增。
什么是多工厂类的工厂方法模式?
多个工厂类,是因为有多个产品,每个产品可能会有自己不同的初始化过程,无法在一个工厂方法中初始化所有的产品对象,那样会造成工厂方法结构不清晰。所以为每一个产品制定一个工厂方法来创建产品对象。
对于多工厂的工厂方法模式,当需要增加一个产品时,稍微会变得复杂,需要新增一个产品类,实现了产品接口,并且增加对应的一个工厂类,实现了工厂类的接口或抽象类。
现在考虑一个问题,每个人种都有男性和女性,那如何去创建黑人男性对象,黑人女性对象,白人男性等对象呢?
一、什么是抽象工厂模式?
Provide an interface for creating families of related or dependent objects without specifying their
concrete classes;
为创建一组或相互依赖的对象提供一个接口,并且不需要指定它们的具体类。
二、示例
1.女娲造人示例
由于在工厂方法模式中,女娲只设定了人种,但是却没有设计性别。现在加上性别,也就是产品类有了下级。先看类图:
代码:
//产品类接口
public interface Human {
/**
* 肤色
*/
void getColor();
/**
* 语言
*/
void say();
/**
* 设置性别
*/
void setSex();
}
//产品类抽象类1
public abstract class AbstractYellowHuman implements Human {
@Override
public void getColor() {
System.out.println("黄种人");
}
@Override
public void say() {
System.out.println("说中文");
}
}
//产品类抽象类2
public abstract class AbstractWhiteHuman implements Human {
@Override
public void getColor() {
System.out.println("白种人");
}
@Override
public void say() {
System.out.println("说英语");
}
}
//产品类抽象类3
public abstract class AbstractBlackHuman implements Human {
@Override
public void getColor() {
System.out.println("黑种人");
}
@Override
public void say() {
System.out.println("说非洲话");
}
}
为了加入性别,也就是给产品类分级,分别实现了不同的产品抽象类:
//产品类再分级1
public class FemaleBlackHuman extends AbstractBlackHuman {
@Override
public void setSex() {
System.out.println("黑人女性");
}
}
//产品类再分级2
public class FemaleWhiteHuman extends AbstractWhiteHuman {
@Override
public void setSex() {
System.out.println("白人女性");
}
}
//产品类再分级3
public class FemaleYellowHuman extends AbstractYellowHuman {
@Override
public void setSex() {
System.out.println("黄人女性");
}
}
public class MaleBlackHuman extends AbstractBlackHuman {
@Override
public void setSex() {
System.out.println("黑人男性");
}
}
public class MaleWhiteHuman extends AbstractWhiteHuman {
@Override
public void setSex() {
System.out.println("白人男性");
}
}
public class MaleYellowHuman extends AbstractYellowHuman {
@Override
public void setSex() {
System.out.println("黄人男性");
}
}
接下来,有多少个产品族,那么在抽象工厂类中,就应该有多少个创建方法。这里有三个产品族,分别是黑人,白人和黄人,所以在工厂类中就应该有三个创建对象的抽象方法。
public interface HumanFactory {
/**
* 创建白人
* @return
*/
Human createWhiteHuman();
/**
* 创建黄种人
* @return
*/
Human createYellowHuman();
/**
* 创建黑人
* @return
*/
Human createBlackHuman();
}
有几个产品分级,就应该有几个工厂。这里有两个产品分级,就是男性和女性。
public class FemaleFactory implements HumanFactory {
@Override
public Human createWhiteHuman() {
return new FemaleWhiteHuman();
}
@Override
public Human createYellowHuman() {
return new FemaleYellowHuman();
}
@Override
public Human createBlackHuman() {
return new FemaleBlackHuman();
}
}
public class MaleFactory implements HumanFactory {
@Override
public Human createWhiteHuman() {
return new MaleWhiteHuman();
}
@Override
public Human createYellowHuman() {
return new MaleYellowHuman();
}
@Override
public Human createBlackHuman() {
return new MaleBlackHuman();
}
}
这样产品和工厂都定义完成了。
分析:
1.有一个产品接口,因为产品都属于这个产品类。
2.有三个产品族,即黑人,白人,黄人。
3.每个产品族,有两个产品等级。即男性,女性。
4.有两个抽象工厂类,那是因为有两个产品等级。
5.每个抽象工厂类中有三个方法,那是因为有三个产品族。
2.通用代码
![抽象工厂模式通用类图](https://img-blog.csdnimg.cn/2020092223000892.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3p4eXkyNjI3,size_16,color_FFFFFF,t_70#pic_center)1.产品接口
public interface Product {
/**
* 所有产品的公共方法
*/
public void common();
/**
* 相同方法名不同的业务逻辑
*/
public void doSomething();
}
2.产品族
public abstract class AbstractProductA implements Product {
@Override
public void common() {
System.out.println("产品族的公共方法1");
}
}
public abstract class AbstractProductB implements Product {
@Override
public void common() {
System.out.println("产品族的公共方法2");
}
}
3.产品等级
public class ProductA1 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品族A类的1号产品");
}
}
public class ProductA2 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品族A类的2号产品");
}
}
public class ProductB1 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("产品族B类的1号产品");
}
}
public class ProductB2 extends AbstractProductB{
@Override
public void doSomething() {
System.out.println("产品族B类的2号产品");
}
}
4.抽象工厂类
public abstract class AbstractCreator {
/**
* 生产A类产品
* @return
*/
public abstract AbstractProductA createProductA();
/**
* 产生B类产品
* @return
*/
public abstract AbstractProductB createProductB();
}
5.工厂类
public class Creator1 extends AbstractCreator {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
public class Creator2 extends AbstractCreator {
@Override
public AbstractProductA createProductA() {
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ProductB2();
}
}
三、抽象工厂模式的优缺点
抽象工厂模式的优点
1.封装性:调用产品类对象的高层模块不用关心对象是如何创建出来的,因为创建对象的工作,由工厂类完成了。
2.产品族内的约束为非公开状态。
抽象工厂模式的缺点
1.难以扩展,如果想要在产品族中增加一个C产品,那么需要添加产品类,并且需要添加工厂类的方法等。这违反了开闭原则。对修改关闭,对扩展开放。
注意事项
上面说的难以扩展是指产品族难以扩展,而不是产品等级难以扩展。如果想要扩展产品等级,也很容易。比如想要在女娲造人中增加一个产品等级:人妖。
步骤:
1.首先增加三个产品类,白人人妖,黄人人妖,黑人人妖。
2.再创建一个工厂类,负责创建不同肤色的人妖。
总结
1.简单工厂模式和工厂方法模式,容易扩展产品族,而难于扩展产品等级。
2.抽象工厂模式容易扩展产品等级,而难于扩展产品族。