Joh*_*der 5 c++ algorithm design-patterns
大家好,
有人可以解释一下Factory方法设计模式和Bridge模式之间的区别吗?
因为据我所知,这两种设计模式都用于分隔接口和实现:
将抽象与实现分离。抽象将客户端代码与实现分开。因此,可以在不影响客户端代码的情况下更改实现,并且在实现更改时无需编译客户端代码。
工厂方法:
没有工厂方法的问题:
在某些情况下,我们有一个包含一些类的库来实现客户端业务逻辑。在客户端应用程序中,我们创建库类的对象以完成任务。
但是有时,根据客户要求合并其他功能,我们可能需要在库中添加其他类。然后,我们需要在客户端应用程序中创建新类的对象。
因此,每次在库端进行新更改时,客户端都需要在其末端进行一些相应的更改并重新编译代码。
使用工厂方法:
为避免此问题,我们使用Factory方法将对象创建与客户端应用程序分离。客户只需要调用库的工厂方法,而不必担心对象创建的实际实现。
因此,我们创建Factory方法来创建对象并将其移动到单独的实现文件中。现在,实现文件是唯一需要了解派生类的文件。因此,如果对任何派生类进行了更改或添加了任何新类,则实现文件是唯一需要重新编译的文件。使用工厂的每个人都只会关心该接口,该接口在应用程序的整个生命周期中都应保持一致。
客户端应用程序交互->工厂方法和调用->实现
如果我采用以下示例程序,则在添加任何类或对该类进行任何更改之后,仅重新编译Vehicle.cpp文件就足够了吗?而且在创建工厂方法时,我们是否使用静态方法?
车辆
#include <iostream>
using namespace std;
enum VehicleType {
VT_TwoWheeler, VT_ThreeWheeler, VT_FourWheeler
};
// Library classes
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
Vehicle.cpp(实施文件)
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
Run Code Online (Sandbox Code Playgroud)
Client.h文件
// Client class
class Client {
public:
// Client doesn't explicitly create objects
// but passes type to factory method "Create()"
Client()
{
VehicleType type = VT_ThreeWheeler;
pVehicle = Vehicle::Create(type);
}
~Client() {
if (pVehicle) {
delete[] pVehicle;
pVehicle = NULL;
}
}
Vehicle* getVehicle() {
return pVehicle;
}
private:
Vehicle *pVehicle;
};
// Driver program
int main() {
Client *pClient = new Client();
Vehicle * pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请提供您对此的想法。
提前致谢。
工厂方法是关于创建对象的灵活性,可以创建新对象,在创建基本代码时未知。例如,假设您正在设计 IO 卡的接口包装器以与您的项目集成。您从 Decklink 卡和 Bluefish 卡开始。稍后你想添加Matrox卡而不修改任何过去的代码,工厂模式将帮助你。
桥接模式更多的是关于将接口与实现分离(隐藏复杂的代码)。
在代码中注意:假设您想添加 VT_FiveWheeler - 您必须修改 Vehicle.h 以添加枚举 VehicleType (听起来很糟糕)。Create 方法可以是静态的,也可以是一个简单的辅助函数,如下所示:
namespace Vehicle {
class Vehicle {
public:
virtual void printVehicle() = 0;
};
}
namespace Vehicle {
namespace TwoWheeler {
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
};
shared_ptr<Vehicle> create() { return make_shared<TwoWheeler>(); }
}
}
namespace Vehicle {
namespace ThreeWheeler {
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
};
shared_ptr<Vehicle> create() { return make_shared<ThreeWheeler>(); }
}
}
namespace Vehicle {
class factory
{
typedef function<shared_ptr<Vehicle>(void) > func_t;
public:
//register a vehicle
void register_vehicle(const string& name, func_t func)
{
registered_vehicles_.insert(make_pair(name, func));
}
//to create a vehicle
shared_ptr<Vehicle> create_vehicle(string name)
{
return registered_vehicles_[name]();
}
map<string, func_t> get() { return registered_vehicles_; }
private:
map<string, func_t> registered_vehicles_;
};
}
Vehicle::factory my_vehicle_factory;
int main() {
//register the vehicle in the factory first
my_vehicle_factory.register_vehicle("TwoWheeler", Vehicle::TwoWheeler::create);
auto p1 = my_vehicle_factory.create_vehicle("TwoWheeler");
auto p2 = my_vehicle_factory.create_vehicle("TwoWheeler");
// A new vehicle has arrived, so first registered it
my_vehicle_factory.register_vehicle("ThreeWheeler", Vehicle::ThreeWheeler::create);
auto p3 = my_vehicle_factory.create_vehicle("ThreeWheeler");
p1->printVehicle();
p2->printVehicle();
p3->printVehicle();
}
Run Code Online (Sandbox Code Playgroud)