設計模式
設計模式是用來解決重複性問題,但是不同的語言有不同的特性,所以就算是相同的設計模式在不同的語言,會有所差異。
為何要用設計模式?
什麼!又要改,是要改幾次啊!!!?
時常聽到軟體工程師講這句話,不論事前如何謹慎規劃系統架構,我們仍會遇到需求變更、bug等,使軟體工程師不斷修改程式碼,不論是敏捷開發的SOLID原則或是設計模式,共同目標是為了讓程式碼更容易維護且保有擴充性。
物件導向程式設計SOLID原則
S: 單一職責(SRP)
單一職責指一個類別只負責一件事,但要注意的是並非一個類別只有一個方法,就如同一台車要在路上行駛,並不代別這台車只擁有路上行駛這個方法,事實上是由前進、後退、左轉、右轉、煞車等功能組成。從另一個角度來看,雖一台車由很多機構組成,每個機構的功能也有所不同,但駕駛人只需要了解如何開車,不用清楚內部結構,對於技師來說,才需要了解零件功能,所以規劃一個類別的責任需視需求而定。
O: 開放/封閉原則(OCP)
開放/封閉原則指的是一個物件導向程式設計時,必須保有開放(擴充性),隨時可以擴充新功能,但在擴充需求時又不影響到舊功能,故舊程式碼應為封閉修改的。
L: 替換原則(LSP)
子類別可以替換掉父類別而不影響程式架構,也就是說子類別可以執行父類別想做的事。
I: 介面隔離原則(ISP)
將不同的功能透過介面分離出來。
D: 依賴反轉原則(DIP)
高階模組不該依賴低階模組,兩個都應依賴於抽象概念上;抽象不依賴細節,而是細節依賴在抽象概念。
單例模式(Singleton)
- 保證一個類別只能產生一個物件
- 須提供存取該物件的統一方法
- 貪婪單例模式:一開始new類別的instance,並將建構子宣告為private,這樣其他程式就無法再new出新物件
#define NULL nullptr
#include <iostream>
using namespace std;
class Singleton {
private:
volatile static Singleton *instance;
Singleton() {
cout << "建立物件..." << endl;
}
public:
volatile static Singleton *getInstance() {
if (instance == NULL) {
instance = new Singleton();
}
return instance;
}
};
volatile Singleton* Singleton::instance = NULL;
int main() {
volatile Singleton *instance1 = Singleton::getInstance();
volatile Singleton *instance2 = Singleton::getInstance();
int addr1 = (int)instance1;
int addr2 = (int)instance2;
cout << "位址1 = " << hex << addr1 << endl;
cout << "位址2 = " << hex << addr2 << endl;
delete instance1;
return 0;
}
簡單工廠模式(Simple Factory)
- 使用者透過工廠來取得產品
- 使用者無需知道工廠如何生產產品
簡單工廠模式又稱靜態工廠模式,傳入不同參數取得不同的類別物件。
一訓練營為簡單的工廠,裡面的冒險者有弓箭手、鬥士等,冒險者則為產品的父類別,弓箭手與鬥士則為實體產品,如果有人要招募冒險者,僅需請訓練營幫忙訓練冒險者,無需理解訓練過程,如果要新增新型態冒險者,僅需於訓練冒險者的方法增加if else 或 switch case分支即可,但這樣直接修改訓練營的類別違反了開放/封閉原則,所以不算健全的設計模式,但用於小型的軟體架構中很好用,實務上也常會用到此種簡單的模式,而明天會進一步討論工廠模式及抽象工廠模式。
類別圖
#include <iostream>
#include <string>
using namespace std;
//產品(麵包)
class Bread
{
protected:
string product_name;
public:
void order() {
cout << "點餐: " << product_name << endl;
}
void bake() {
cout << product_name << "烘烤中..." << endl;
}
void finish() {
cout << product_name << "出爐!" << endl << endl;
}
};
//實作類別
class Bagel : public Bread
{
public:
Bagel() {
product_name = "貝果";
}
};
class FrenchBread : public Bread
{
public:
FrenchBread() {
product_name = "法國麵包";
}
};
class Toast : public Bread
{
public:
Toast() {
product_name = "吐司";
}
};
//麵包工廠
Bread *BreadFactory(string name)
{
Bread *bread = NULL;
if (name == "Bagel") {
bread = new Bagel();
}
else if (name == "French Bread") {
bread = new FrenchBread();
}
else if (name == "Toast") {
bread = new Toast();
}
else {
bread = NULL;
}
while (bread != NULL)
{
bread -> order();
bread -> bake();
bread -> finish();
return bread;
}
}
//測試碼
int main()
{
Bread *order1 = BreadFactory("Bagel");
Bread *order2 = BreadFactory("Toast");
Bread *order3 = BreadFactory("French Bread");
delete order1;
delete order2;
delete order3;
return 0;
}
聲明: 內文為書摘,書本提供之範例用Java寫的,有興趣可以參考原著,以上C++程式為個人之練習,如有疏漏,歡迎前輩批評指教,謝謝!