[设计模式] —— Abstract Factory 抽象工厂模式

抽象工厂

通过对象创建模式,绕开 new,来避免对象创建(new)过程中导致的紧耦合(new 需要依赖具体类),从而支持对象创建的稳定,它是抽象接口后的第一步工作

动机

主要是解决一系列”相互依赖的对象“,工厂方法是解决”单个对象“,即多个 Factory 组成一个总的基类。

定义

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

示例代码
class EmployeeDAO {
public:
 vector<Employee> GetEmployees() {
     SqlConnection* connection = new SqlConnection();
     connection->ConnectionString = "...";

     SqlCommand* command = new SqlCommand();
     command->CommandText = "@@@";
     command->SetConnection(connection);

     SqlDataReader* reader = command->ExecuteReader();
     while(reader->Read()) {
         // ...
     }
 }
};

假设我们现在有一个 EmployeeDAO 可以获取访问数据库,然后获取员工的一些信息,这里连接数据库的过程就是 Sqlxxx 相关类之间相互依赖,并且这里都是依赖了具体的类,之后如果需求有变化,例如使用其他数据库,这个类就不适用了。那么了解过工厂模式的可以知道,现在我们想实现变化,需要加一层,新的抽象来创建具体的类,这里需要为每一个 new 过的类创建一个工厂基类。

// connection 工厂基类
class ConnectionFactory {
public:
 virtual Connection* CreateConnection() = 0;
 virtual ~ConnectionFactory(){}
};
// connection 工厂具体类
class SqlConnectionFactory : public ConnectionFactory {
 public:
  virtual Connection* (){ return new SqlConnection(); }
}
// connection 工厂具体类
class OracleConnectionFactory : public ConnectionFactory {
 public:
  virtual Connection* (){ return new OracleConnection(); }
}
// command 工厂基类
class CommandFactory {
public:
 virtual Command* CreateCommand() = 0;
 virtual ~CommandFactory(){}
};
// command 工厂具体类
class SqlCommandFactory : public CommandFactory {
 public:
  virtual Command* (){ return new SqlCommand(); }
}
// command 工厂具体类
class OracleCommandFactory : public CommandFactory {
 public:
  virtual Command* (){ return new OracleCommand(); }
}
// dataReader 工厂基类
class DataReaderFactory {
public:
 virtual DataReader* CreateDataReader() = 0;
 virtual ~DataReaderFactory(){}
};
// dataReader 工厂具体类
class SqlDataReaderFactory : public DataReaderFactory {
 public:
  virtual DataReader* (){ return new SqlDataReader(); }
}
// dataReader 工厂具体类
class OracleDataReaderFactory : public DataReaderFactory {
 public:
  virtual DataReader* (){ return new OracleDataReader(); }
}

class EmployeeDAO {
    ConnectionFactory* connectionFactory; // 多态
    CommandFactory* commandFactory;
    DataReaderFactory* dataReaderFactory;
public:
 // 这里省略了EmployeeDAO 初始化成员变量的构造函数
 
 vector<Employee> GetEmployees() {
     Connection* connection = connectionFactory->CreateConnection();
     connection->ConnectionString = "...";

     Command* command = commandFactory->CreateCommand();
     command->CommandText = "@@@";
     command->SetConnection(connection); // 关联性

     DataReader* reader = command->ExecuteReader(); // 关联性
     while(reader->Read()) {
         // ...
     }
 }
};

上面的实现采用工厂模式的思路,确实解决了创建对象依赖具体类导致程序脆弱的问题,但是现在还有一个问题就是,数据库之间的操作需要保持一致性,当前 3 个独立的抽象工厂作为参数传入 EmployeeDAO 类,但是现在的结构并不能保证它们是一致的,完全可以出现传入了 Sql 的 connection,却传入了 oracle 的 command,这样肯定会报错的。因此Abstract Factory 抽象工厂的模式会更近一步,将相关之间有关联性的工厂基类都放在一起。

class IDBFactory {
public:
 virtual Connection* CreateConnection() = 0;
 virtual Command* CreateCommand() = 0;
 virtual DataReader* CreateDataReader() = 0;

 virtual ~IDBFactory(){}
};

class IDBSqlFactory : public IDBFactory{
public:
   virtual Connection* () { return new SqlConnection(); }
   virtual Command* () { return new SqlCommand(); }
   virtual DataReader* () { return new SqlDataReader(); }
};

class IDBOracleFactory : public IDBFactory{
public:
   virtual Connection* () { return new OracleConnection(); }
   virtual Command* () { return new OracleCommand(); }
   virtual DataReader* () { return new OracleDataReader(); }
};

class EmployeeDAO {
    IDBFactory* idbFactory;
public:
 vector<Employee> GetEmployees() {
     Connection* connection = idbFactory->CreateConnection();
     connection->ConnectionString = "...";

     Command* command = idbFactory->CreateCommand();
     command->CommandText = "@@@";
     command->SetConnection(connection); // 关联性

     DataReader* reader = command->ExecuteReader(); // 关联性
     while(reader->Read()) {
         // ...
     }
 }
};

至此,上面就完成了 Abstract Factory 抽象工厂模式,其中将相互关联的工厂接口合并在一起,实现了高内聚,多态实现了松耦合。

结构图
总结
  • 如果没有应对”多系列对象构建“的需求变化,则没有必要使用 Abstract Factory 模式,简单工厂就足够了。
  • ”系列对象“是指某一特定系列下的对象之间有相互依赖或者作用关系,不同系列的对象之间不能相互依赖(sql 的 command 不能依赖 oracle 的 connection)
  • Abstract Factory 主要用于应对”新系列“的需求变动,缺点在于难以应对”新对象“的需求变动(在 connection,command,datareader 的基础上增加功能接口),抽象基类的要求就是要稳定

其他设计模式汇总:
[设计模式] —— 设计模式的介绍及分类

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Abstract Factory Pattern是一种设计模式,它是创建对象的工厂模式的变体,允许对象在运行时被替换。 Abstract Factory模式提供了一种方法,可以创建一组相关或相互依赖的对象,而不需要明确指定其具体类。 下面是一个C语言的代码示例,该代码实现了一个抽象工厂模式,该模式创建一组车辆: ```c #include <stdio.h> typedef struct IVehicle IVehicle; struct IVehicle { void (*Drive)(IVehicle *); }; typedef struct Car Car; struct Car { IVehicle base; int wheelCount; }; void Car_Drive(IVehicle *vehicle) { Car *car = (Car *)vehicle; printf("Driving a car with %d wheels\n", car->wheelCount); } typedef struct Bike Bike; struct Bike { IVehicle base; int pedalCount; }; void Bike_Drive(IVehicle *vehicle) { Bike *bike = (Bike *)vehicle; printf("Riding a bike with %d pedals\n", bike->pedalCount); } typedef struct IVehicleFactory IVehicleFactory; struct IVehicleFactory { IVehicle *(*CreateVehicle)(IVehicleFactory *); }; typedef struct CarFactory CarFactory; struct CarFactory { IVehicleFactory base; }; IVehicle *CarFactory_CreateVehicle(IVehicleFactory *factory) { Car *car = (Car *)malloc(sizeof(Car)); car->base.Drive = &Car_Drive; car->wheelCount = 4; return (IVehicle *)car; } typedef struct BikeFactory BikeFactory; struct BikeFactory { IVehicleFactory base; }; IVehicle *BikeFactory_CreateVehicle(IVehicleFactory *factory) { Bike *bike = (Bike *)malloc(sizeof(Bike)); bike->base.Drive = &Bike_Drive; bike->pedalCount = 2; return (IVehicle *)bike; } int main(int argc, char *argv[]) { CarFactory carFactory = { { &CarFactory_CreateVehicle } }; IVehicle *vehicle = carFactory.base.CreateVehicle((IVehicleFactory *)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值