20230423 15. 抽象工厂模式 - 数据库

介绍

工厂方法模式是定义一个用于创建对象的接口,让子类决定实例化哪一个类。

抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

抽象工厂模式

  • AbstractProductA和AbstractProductB是两个抽象产品,之所以为抽象,是因为它们都有可能有两种不同的实现
  • ProductA1、ProductA2和ProductB1、ProductB2就是对两个抽象产品的具体分类的实现
  • IFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法
  • ConcreteFactory1和ConcreteFactory2就是具体的工厂了

通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂

抽象工厂模式的好处

  • 便是易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置
  • 它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中

缺点:增加一个新产品Project,至少要增加三个类,IProject、SqlserverProject、AccessProject,还需要更改IFactory、SqlserverFactory和AccessFactory才可以完全实现

所有在用简单工厂的地方,都可以考虑用反射技术来去除switch或if,解除分支判断带来的耦合。

抽象工厂模式和工厂方法模式的不同点:

  • 继承方式不同:工厂方法模式中的工厂类必须继承同一个抽象类或接口,而抽象工厂类可以继承多个抽象类或接口。
  • 创建对象的方式不同:工厂方法模式中的工厂类只能创建一种产品,而抽象工厂类可以创建多种不同的产品。
  • 设计思路不同:工厂方法模式强调工厂的通用性,以及与产品之间的关系,而抽象工厂类则强调抽象产品的概念。
  • 适用场景不同:工厂方法模式适用于创建同类型的产品族,而抽象工厂类适用于创建任意类型的产品族。

代码示例

AbstractProduct 抽象产品

public interface IUser {
    void insert();

    void get();
}

public interface IDepartment {
    void insert();

    void get();
}

产品实现

public class AccessDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("access 插入一条 department 信息");
    }

    @Override
    public void get() {
        System.out.println("access 获得一条 department 信息");
    }
}

public class AccessUser implements IUser {
    @Override
    public void insert() {
        System.out.println("access 插入一条 user 信息");
    }

    @Override
    public void get() {
        System.out.println("access 获得一条 user 信息");
    }
}

public class SqlServerDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("sql server 插入一条 department 信息");
    }

    @Override
    public void get() {
        System.out.println("sql server 获得一条 department 信息");
    }
}

public class SqlServerUser implements IUser {
    @Override
    public void insert() {
        System.out.println("sql server 插入一条 user 信息");
    }

    @Override
    public void get() {
        System.out.println("sql server 获得一条 user 信息");
    }
}

用反射+配置文件实现的工厂

public class DataAccess {
    private static String db = null;


    public static IUser createUser() {
        String db = getDb();
        String className = "study.hwj.p15." + db + "User";
        return (IUser) getInstance(className);
    }

    public static IUser createDepartment() {
        String db = getDb();
        String className = "study.hwj.p15." + db + "Department";
        return (IUser) getInstance(className);
    }

    private static Object getInstance(String className) {
        try {
            return Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getDb() {
        if (db == null) {
            Properties properties = new Properties();
            try {
                properties.load(new FileReader("D:\\Develop\\workspace\\study\\study-design-pattern\\src\\main\\java"
                        + "\\study\\hwj\\p15\\db.properties"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            db = properties.getProperty("db");
        }
        return db;
    }
}

db.properties

# 这里的值要和类名的前缀相同
db=SqlServer

客户端类

public class Test {
    public static void main(String[] args) {
        IUser user = DataAccess.createUser();
        user.insert();
        user.get();
    }
}
posted @ 2023-06-19 09:46  流星<。)#)))≦  阅读(19)  评论(0编辑  收藏  举报