定义
为创建一组相关或相互依赖的对象(涉及到多个产品系列的问题)提供一个接口,而且无须指定它们的具体类。
(抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。)
通用类图
在工厂方法模式中,抽象产品类 Product 负责定义产品的共性,实现对事物最抽象的定义;AbstractFactory 为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂 ContreteFactory 完成的。
通用源码类图
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
案例代码
(案例 1)通用源码类图
public class Client1 {
//场景类(没有任何一个方法与实现类有关系)
public static void main(String[] args) {
//在具体的业务中产生一个与实现无关的对象。
//对于一个产品来说,只要知道它的工厂方法就可以直接产生一个产品对象,无须关心它的实现类。
AbstractCreator creator1 = new Creator1();
AbstractProductA productA = creator1.createProductA();
productA.createProductA();
AbstractCreator creator2 = new Creator2();
AbstractProductB productB = creator2.createProductB();
productB.createProductB();
}
}
/**
* AbstractProductA这就是具体的产品家族,每个具体工厂都能生产一整组的产品。
*/
abstract class AbstractProductA{
protected abstract void createProductA();
}
class ProductA1 extends AbstractProductA{
@Override
protected void createProductA() {
System.out.println("ProductA1");
}
}
class ProductA2 extends AbstractProductA{
@Override
protected void createProductA() {
System.out.println("ProductA2");
}
}
abstract class AbstractProductB{
protected abstract void createProductB();
}
class ProductB1 extends AbstractProductB{
@Override
protected void createProductB() {
System.out.println("ProductB1");
}
}
class ProductB2 extends AbstractProductB{
@Override
protected void createProductB() {
System.out.println("ProductB2");
}
}
/**
* 抽象工厂AbstractCreator的职责是定义每个工厂要实现的功能,
* 在下述通用代码中,抽象工厂类定义了两个产品族的产品创建。
* 注意:有N个产品族,在抽象工厂类中就应该有N个创建方法。
*/
abstract class AbstractCreator{
protected abstract AbstractProductA createProductA();
protected abstract AbstractProductB createProductB();
}
/**
* 有M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
* 创建产品是由具体的实现类来完成的。
*/
class Creator1 extends AbstractCreator{
@Override
protected AbstractProductA createProductA() {
return new ProductA1();
}
@Override
protected AbstractProductB createProductB() {
return new ProductB1();
}
}
/**
* 这个具体工厂实现不同的产品家族。要创建一个产品,客户只要使用其中的一个工厂而
* 完全不需要实例化任何产品对象。
* 创建产品是由具体的实现类来完成的。
*/
class Creator2 extends AbstractCreator{
@Override
protected AbstractProductA createProductA() {
return new ProductA2();
}
@Override
protected AbstractProductB createProductB() {
return new ProductB2();
}
}
(案例 2)数据访问程序案例
案例 2-1(初始案例)
/**
* 数据访问程序案例1:初始案例
*/
public class Client1 {
public static void main(String[] args) {
User user = new User();
SqlServerUser sqlServerUser = new SqlServerUser();
sqlServerUser.insert(user);
sqlServerUser.get(1);
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class SqlServerUser{
public void insert(User user){
System.out.println("insert");
}
public User get(int id){
System.out.println("get");
return null;
}
}
案例 2-2(工厂方法模式)
/**
* 数据访问程序案例2:工厂方法模式
*/
public class Client2 {
public static void main(String[] args) {
IFactory factory = new SqlServerFactory();
IUser user = factory.createUser();
user.insert(new User());
user.get(1);
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IUser{
void insert(User user);
User get(int id);
}
class SqlServerUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert SqlServerUser");
}
@Override
public User get(int id) {
System.out.println("get SqlServerUser");
return null;
}
}
class AccessUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert AccessUser");
}
@Override
public User get(int id) {
System.out.println("get AccessUser");
return null;
}
}
interface IFactory{
IUser createUser();
}
class SqlServerFactory implements IFactory{
@Override
public IUser createUser() {
return new SqlServerUser();
}
}
class AccessFactory implements IFactory{
@Override
public IUser createUser() {
return new AccessUser();
}
}
案例 2-3(抽象工厂模式)
/**
* 数据访问程序案例3:抽象工厂模式
*/
public class Client3 {
public static void main(String[] args) {
IFactory factory = new SqlServerFactory();
IUser user = factory.createUser();
user.insert(new User());
user.get(1);
IDepartment department = factory.createDepartment();
department.insert(new Department());
department.get(1);
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IUser{
void insert(User user);
User get(int id);
}
class SqlServerUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert SqlServerUser");
}
@Override
public User get(int id) {
System.out.println("get SqlServerUser");
return null;
}
}
class AccessUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert AccessUser");
}
@Override
public User get(int id) {
System.out.println("get AccessUser");
return null;
}
}
class Department{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IDepartment{
void insert(Department department);
Department get(int id);
}
class SqlServerDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert SqlServerDepartment");
}
@Override
public Department get(int id) {
System.out.println("get SqlServerDepartment");
return null;
}
}
class AccessDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert AccessDepartment");
}
@Override
public Department get(int id) {
System.out.println("get AccessDepartment");
return null;
}
}
interface IFactory{
IUser createUser();
IDepartment createDepartment();
}
class SqlServerFactory implements IFactory{
@Override
public IUser createUser() {
return new SqlServerUser();
}
@Override
public IDepartment createDepartment() {
return new SqlServerDepartment();
}
}
class AccessFactory implements IFactory{
@Override
public IUser createUser() {
return new AccessUser();
}
@Override
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
案例 2-4(简单工厂模式改进的抽象工厂模式)
/**
* 数据访问程序案例4:用简单工厂模式改进的抽象工厂模式
*/
public class Client4 {
public static void main(String[] args) {
IUser user = DataAccess.createUser();
user.insert(new User());
user.get(1);
IDepartment department = DataAccess.createDepartment();
department.insert(new Department());
department.get(1);
}
}
class DataAccess{
private static final String DB = "sqlServer";
/*private static final String DB = "access";*/
public static IUser createUser(){
IUser result = null;
switch (DB){
case "sqlServer":
result = new SqlServerUser();
break;
case "access":
result = new AccessUser();
break;
}
return result;
}
public static IDepartment createDepartment(){
IDepartment result = null;
switch (DB){
case "sqlServer":
result = new SqlServerDepartment();
break;
case "access":
result = new AccessDepartment();
break;
}
return result;
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IUser{
void insert(User user);
User get(int id);
}
class SqlServerUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert SqlServerUser");
}
@Override
public User get(int id) {
System.out.println("get SqlServerUser");
return null;
}
}
class AccessUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert AccessUser");
}
@Override
public User get(int id) {
System.out.println("get AccessUser");
return null;
}
}
class Department{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IDepartment{
void insert(Department department);
Department get(int id);
}
class SqlServerDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert SqlServerDepartment");
}
@Override
public Department get(int id) {
System.out.println("get SqlServerDepartment");
return null;
}
}
class AccessDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert AccessDepartment");
}
@Override
public Department get(int id) {
System.out.println("get AccessDepartment");
return null;
}
}
案例 2-5(反射 + 抽象工厂)
/**
* 数据访问程序案例5:用反射+抽象工厂
*/
public class Client5 {
public static void main(String[] args) {
IUser user = DataAccess.createUser();
user.insert(new User());
user.get(1);
IDepartment department = DataAccess.createDepartment();
department.insert(new Department());
department.get(1);
}
}
class DataAccess{
private static final String DB = "SqlServer";
/*private static final String DB = "Access";*/
public static IUser createUser(){
IUser result = null;
try {
Class userClass = Class.forName("com.mbox.chouxianggongchang2.example5." + DB + "User");
Object obj = userClass.newInstance();
result = (IUser)obj;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
public static IDepartment createDepartment(){
IDepartment result = null;
try {
Class userClass = Class.forName("com.mbox.chouxianggongchang2.example5." + DB + "Department");
Object obj = userClass.newInstance();
result = (IDepartment)obj;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IUser{
void insert(User user);
User get(int id);
}
class SqlServerUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert SqlServerUser");
}
@Override
public User get(int id) {
System.out.println("get SqlServerUser");
return null;
}
}
class AccessUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert AccessUser");
}
@Override
public User get(int id) {
System.out.println("get AccessUser");
return null;
}
}
class Department{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IDepartment{
void insert(Department department);
Department get(int id);
}
class SqlServerDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert SqlServerDepartment");
}
@Override
public Department get(int id) {
System.out.println("get SqlServerDepartment");
return null;
}
}
class AccessDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert AccessDepartment");
}
@Override
public Department get(int id) {
System.out.println("get AccessDepartment");
return null;
}
}
案例 2-6(反射 + 抽象工厂 + 配置文件)
import java.io.InputStream;
import java.util.Properties;
/**
* 数据访问程序案例5:用反射+抽象工厂+配置文件
* maven项目在resource目录下新建了config.properties文件,内容为DB=SqlServer。
*/
public class Client6 {
public static void main(String[] args) {
IUser user = DataAccess.createUser();
user.insert(new User());
user.get(1);
IDepartment department = DataAccess.createDepartment();
department.insert(new Department());
department.get(1);
}
}
class DataAccess{
private static String DB = null;
static {
try {
InputStream inputStream = Client6.class.getClassLoader().getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(inputStream);
System.out.println(properties);
DB = properties.getProperty("DB");
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static IUser createUser(){
IUser result = null;
try {
Class userClass = Class.forName("com.mbox.chouxianggongchang2.example6." + DB + "User");
Object obj = userClass.newInstance();
result = (IUser)obj;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
public static IDepartment createDepartment(){
IDepartment result = null;
try {
Class userClass = Class.forName("com.mbox.chouxianggongchang2.example6." + DB + "Department");
Object obj = userClass.newInstance();
result = (IDepartment)obj;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IUser{
void insert(User user);
User get(int id);
}
class SqlServerUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert SqlServerUser");
}
@Override
public User get(int id) {
System.out.println("get SqlServerUser");
return null;
}
}
class AccessUser implements IUser{
@Override
public void insert(User user) {
System.out.println("insert AccessUser");
}
@Override
public User get(int id) {
System.out.println("get AccessUser");
return null;
}
}
class Department{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IDepartment{
void insert(Department department);
Department get(int id);
}
class SqlServerDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert SqlServerDepartment");
}
@Override
public Department get(int id) {
System.out.println("get SqlServerDepartment");
return null;
}
}
class AccessDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("insert AccessDepartment");
}
@Override
public Department get(int id) {
System.out.println("get AccessDepartment");
return null;
}
}
(反射是将程序由编译时转为运行时实例化对象,千万不要说比如通过某个字符串参数来“写死”来实例化不同的对象。)
参考 SpringIOC 和依赖倒置原则。个人理解 Spring 的 IoC 是对抽象工厂模式的升级。
所有在用简单工厂的地方,都可以考虑用反射技术来去除 switch 或 if,解除分支判断带来的耦合。
(案例 3)女娲造人案例
图形结构
代码示例
public class Client7 {
public static void main(String[] args) {
HumanFactory maleHumanFactory = new MaleFactory();
Human maleYellowHuman = maleHumanFactory.createYellowHuman();
maleYellowHuman.getColor();
maleYellowHuman.getSex();
maleYellowHuman.talk();
System.out.println("-------------------");
HumanFactory femaleHumanFactory = new FemaleFactory();
Human femaleYellowHuman = femaleHumanFactory.createYellowHuman();
femaleYellowHuman.getColor();
femaleYellowHuman.getSex();
femaleYellowHuman.talk();
}
}
interface Human{
void getColor();
void talk();
void getSex();
}
abstract class AbstractWhiteHuman implements Human{
@Override
public void getColor() {
System.out.println("白色人种白皮肤");
}
@Override
public void talk() {
System.out.println("白色人种讲话单字节");
}
}
abstract class AbstractBlackHuman implements Human{
@Override
public void getColor() {
System.out.println("黑色人种黑皮肤");
}
@Override
public void talk() {
System.out.println("黑色人种讲话一般听不懂");
}
}
abstract class AbstractYellowHuman implements Human{
@Override
public void getColor() {
System.out.println("黄色人种黄皮肤");
}
@Override
public void talk() {
System.out.println("黄色人种讲话双字节");
}
}
class FemaleYellowHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("黄色人种女性");
}
}
class MaleYellowHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("黄色人种男性");
}
}
class FemaleWhiteHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("白色人种女性");
}
}
class MaleWhiteHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("白色人种男性");
}
}
class FemaleBlackHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("黑色人种女性");
}
}
class MaleBlackHuman extends AbstractYellowHuman{
@Override
public void getSex() {
System.out.println("黑色人种男性");
}
}
interface HumanFactory{
Human createYellowHuman();
Human createWhiteHuman();
Human createBlackHuman();
}
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();
}
}
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();
}
}
抽象工厂与工厂方法区别
在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而 2.0 排量车和 2.4 排量车则称为两个不同的产品族。再具体一点,2.0 排量两厢车和 2.4 排量两厢车属于同一个等级结构,2.0 排量三厢车和 2.4 排量三厢车属于另一个等级结构;而 2.0 排量两厢车和 2.0 排量三厢车属于同一个产品族,2.4 排量两厢车和 2.4 排量三厢车属于另一个产品族。
明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,**如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。**在本例中,如果一个工厂模式提供 2.0 排量两厢车和 2.4 排量两厢车,那么它属于工厂方法模式;如果一个工厂模式是提供 2.4 排量两厢车和 2.4 排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为它提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。
注意事项
一个对象/产品族(或是一组没有任何关系的对象)有相同的约束,则可以使用抽象工厂模式。
抽象工厂模式在增加或修改或删除一个产品时,需要修改相应的几个工厂对象,严重违反了“开闭原则”。
抽象工厂模式的产品族扩展比较困难,而不是产品等级扩展困难。也就是说横向扩展容易,纵向扩展困难。
抽象工厂的方法经常以工厂方法的方式来实现。
解耦方面,抽象工厂使用的是对象,工厂模式使用的是类。
创建对象,抽象工厂通过对象的组合,工厂模式通过继承。
抽象工厂模式和工厂模式都能将对象的创建封装起来,使应用程序解耦,并降低其对特定实现的依赖。
抽象工厂模式:当需要创建产品家族和想让制造的相关产品集合起来。
工厂模式:可以把客户代码从需要实例化的具体类中解耦。或者目前还不知道将来需要实例化的哪些具体类,都可以使用工厂模式。
工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
抽象工厂模式最大的好处是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置;另外,它让具体的创建实例过程与客户端分离,客户单是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
标题:设计模式(三)创建型模式(对象创建型模式)抽象工厂-ABSTRACT FACTORY
作者:yazong
地址:https://blog.llyweb.com/articles/2020/04/22/1587488002879.html