设计模式 -- AbstractFactory(抽象工厂)

抽象工厂(Abstract Factory)

提供一个接口,让该接口负责创建一系列“性关系或相互依赖的对象”,无需指定他们的具体类。

在软件系统中,经常会面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,往往存在着更多系列对象的创建工作。
假设需要写一个数据访问层,那么需要创建一系列对象,比如需要connection对象、command对象等等。同时在不同的数据库选择的时候,也存在变化的问题。所以以下代码是写死的代码,不能很好的适应未来变化。

原先

class SqlConnection {}
class SqlCommand {
    public void setConnection(SqlConnection connection) {}
    public SqlDataReader getSqlDataReader() {
        return new SqlDataReader();
    }
}
class SqlDataReader {
    public boolean read() {
        return true;
    } 
}


class EmployeeDAO{
    void GetEmployees(){
        SqlConnection connection =
            new SqlConnection();

        SqlCommand command =
            new SqlCommand();
        command.setConnection(connection);

        SqlDataReader reader = command.getSqlDataReader();
        while (reader.read()){

        }
    }
};

那么,为了应对数据库变化的情况,那么将数据库访问的一些对象进行向上抽象。

重构

//数据库访问有关的基类
interface IDBConnection {

    void ConnectionString(String s);
};

interface IDBConnectionFactory {
    IDBConnection CreateDBConnection();
};

interface IDBCommand {

};

interface IDBCommandFactory {
    IDBCommand CreateDBCommand();
};


interface IDataReader {

};

interface IDataReaderFactory {
    IDataReader CreateDataReader();
};


//支持SQL Server
class SqlConnection implements IDBConnection {

    @Override
    public void ConnectionString(String s) {

    }
};

class SqlConnectionFactory implements IDBConnectionFactory {

    @Override
    public IDBConnection CreateDBConnection() {
        return null;
    }
};


class SqlCommand implements IDBCommand {

};

class SqlCommandFactory implements IDBCommandFactory {

    @Override
    public IDBCommand CreateDBCommand() {
        return null;
    }
};


class SqlDataReader implements IDataReader {

};

class SqlDataReaderFactory implements IDataReaderFactory {

    @Override
    public IDataReader CreateDataReader() {
        return null;
    }
};

//支持Oracle
class OracleConnection implements IDBConnection {

    @Override
    public void ConnectionString(String s) {

    }
};

class OracleCommand implements IDBCommand {

};

class OracleDataReader implements IDataReader {

};


class EmployeeDAO {
    public IDBConnectionFactory dbConnectionFactory;
    public IDBCommandFactory dbCommandFactory;
    public IDataReaderFactory dataReaderFactory;


    public void GetEmployees() {
        IDBConnection connection =
                dbConnectionFactory.CreateDBConnection();
        connection.ConnectionString("...");

        IDBCommand command =
                dbCommandFactory.CreateDBCommand();
    }
};

对于上面的代码来说,把所有的数据库访问有关的对象都创建了基类,如果为了实现其他的数据库,只需要针对对应的基类派生出子类。那么,其实也就是每个对象的创建都使用了工厂模式。

现在已经能够很好的解决变化的问题,但是这时候存在一个新的问题,那就是,这一系列对象并不是彼此分隔的,比如MySQL的Connection对象对应着MySQL的Commend,如果使用错了,那么肯定会在运行时报错,无法完成我们想要达到的目的。那么这个问题该如何解决呢?

我们可以尝试把对应的一系列的对象放在同一个工厂类中,以此来避免出现这样的问题。

最终代码

//数据库访问有关的基类
interface IDBConnection{

};

interface IDBCommand{

};

interface IDataReader{

};

interface IDBFactory{
     IDBConnection CreateDBConnection();
     IDBCommand CreateDBCommand();
     IDataReader CreateDataReader();
};


//支持SQL Server
class SqlConnection implements IDBConnection{

};
class SqlCommand implements IDBCommand{

};
class SqlDataReader implements IDataReader{

};

class SqlDBFactory implements IDBFactory{
    public IDBConnection CreateDBConnection() {
        return new SqlConnection();
    }
    public IDBCommand CreateDBCommand() {
        return new SqlCommand();
    }
    public IDataReader CreateDataReader() {
        return new SqlDataReader();
    }
};

//支持Oracle
class OracleConnection implements IDBConnection{

};

class OracleCommand implements IDBCommand{

};

class OracleDataReader implements IDataReader{

};

class OracleDBFactory implements IDBFactory {

    @Override
    public IDBConnection CreateDBConnection() {
        return new OracleConnection();
    }

    @Override
    public IDBCommand CreateDBCommand() {
        return new OracleCommand();
    }

    @Override
    public IDataReader CreateDataReader() {
        return new OracleDataReader();
    }
}


class EmployeeDAO{
    IDBFactory dbFactory;

    void GetEmployees(){
        IDBConnection connection =
            dbFactory.CreateDBConnection();

        IDBCommand command =
            dbFactory.CreateDBCommand();

        IDataReader reader = dbFactory.CreateDataReader(); //关联性
    }
};

以上的代码不难看出,把对应的一套工厂封装在了一起,那么,这就是一种AbstractFactory的模式

总结

如果没有对应“多系列对象构建”的需求变化,则没有必要使用Abstract Factory 模式,这时候使用简单的工厂完全可以。
“系列对象”指的是在某一特定系列下的对象之间有相互依赖或作用关系。不同系列的对象之间不能相互依赖。
Abstract Factory 模式主要在于应对“新系列”的需求变动,其缺点在于难以应对“新对象”的需求变动。

posted @ 2022-09-25 15:55  鐡道  阅读(52)  评论(0)    收藏  举报