目錄
- 前言
- 使用簡單工廠改進
- 使用登錄檔改進
- 參考文章
前言
在上一篇文章中我們提到了抽象工廠模式初版程式碼的一些缺點:①客戶端違反開閉原則②提供方違反開閉原則。本文將針對這兩點進行討論
使用簡單工廠改進
對於缺點①,我們可以使用簡單工廠的思路來改進抽象工廠的初版程式碼。對於上一篇文章中的例子,我們去除CameraFactory
、BaslerCameraFactory
和SickCameraFactory
,取而代之的是SimpleFactory
類。
類圖如下:
程式碼如下:
//工廠類
class SimpleFactory
{
public:
BaslerCamera* CreateBaslerCamera()
{
if ("Linux" == os_name_)
{
return new LinuxBaslerCamera();
}
else if ("Windows" == os_name_)
{
return new WindowsBaslerCamera();
}
else
{
return nullptr;
}
}
SickCamera* CreateSickCamera()
{
if ("Linux" == os_name_)
{
return new LinuxSickCamera();
}
else if ("Windows" == os_name_)
{
return new WindowsSickCamera();
}
else
{
return nullptr;
}
}
public:
std::string os_name_ = "Linux";
};
//客戶端
int main()
{
SimpleFactory* camera_factory = new SimpleFactory();
BaslerCamera* basler_camera = camera_factory->CreateBaslerCamera();
basler_camera->OpenCamera();
SickCamera* sick_camera = camera_factory->CreateSickCamera();
sick_camera->OpenCamera();
return 0;
}
注意,上述方法雖然改進了缺點①,但是缺點②仍存在。
使用登錄檔改進
對於缺點②,其本質是:增加新產品時,對工廠類帶來的修改違反了開閉原則。對於這種情況,我們可以參考《設計模式學習(二)工廠模式——工廠方法模式+登錄檔》中提到的登錄檔,來去除switch
或if
這種分支判斷,解除分支判斷帶來的耦合。
對於具體產品,我們可以這樣將它註冊:
class LinuxBaslerCamera : public BaslerCamera
{
public:
~LinuxBaslerCamera() override = default;
bool OpenCamera() override
{
return true;
}
};
ReflectRegister("LinuxBasler", LinuxBaslerCamera);
然後工廠類的程式碼可以簡化為:
class SimpleFactory
{
public:
BaslerCamera* CreateBaslerCamera()
{
std::string name = os_name_ + "Basler";
return Object::CreateObject<BaslerCamera>(name);
}
SickCamera* CreateSickCamera()
{
std::string name = os_name_ + "Sick";
return Object::CreateObject<SickCamera>(name);
}
public:
std::string os_name_ = "Linux";
};
這樣,在產品族增加時(比如增加一個HarmonyOS
),我們只需要在它下面的產品類對應的檔案中使用ReflectRegister
註冊,然後改變os_name_
即可(當然os_name_
也可以在執行時從配置檔案中載入,這樣更好)。
而對於現有的產品族內增加新產品(比如增加一個Huaray
相機),工廠類中還是要增加一個CreateHuarayCamera
函式。
參考文章
1.《大話設計模式》