YAZONG 我的开源

设计模式(三)创建型模式(对象创建型模式)抽象工厂-ABSTRACT FACTORY

 
0 评论0 浏览

定义

为创建一组相关或相互依赖的对象(涉及到多个产品系列的问题)提供一个接口,而且无须指定它们的具体类。

(抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。)

通用类图

image.png

在工厂方法模式中,抽象产品类 Product 负责定义产品的共性,实现对事物最抽象的定义;AbstractFactory 为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂 ContreteFactory 完成的。

通用源码类图

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。

image.png

案例代码

(案例 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)女娲造人案例

图形结构

image.png

代码示例

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();
    }
}

抽象工厂与工厂方法区别

image.png

在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而 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