點擊鏈接閱讀原文,獲取更多技術內容:
(資料圖)
本文從設計原則、創建型模式、結構型模式、行為模式四個方向講述C++的設計模式。
作者 | 恒索
來源 | 阿里開發者公眾號
定義:單一職責原則[1],所謂職責是指類變化的原因。如果一個類有多于一個的動機被改變,那么這個類就具有多于一個的職責。而單一職責原則就是指一個類或者模塊應該 有且只有一個改變的原因。
bad case :IPhone類承擔了協議管理(Dial、HangUp)、數據傳送(Chat)。
good case:
定義:里氏代換原則[2](Liskov Substitution Principle LSP),任何 基類 可以出現的地方, 子類一定可以出現。
bad case :ToyGun繼承了AbstractGun,但Solider在調用KillEnemy()時會報錯(ToyGun無法KillEnemy),即ToyGun無法完全行使AbstractGun的職責。
good case: AbstractToy中將聲音、形狀都委托給AbstractGun處理。
如果子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生“畸變”,則建議斷開父子繼承關系,采用依賴、聚集、組合等關系代替。
定義:依賴倒置原則[3](Dependence Inversion Principle)是程序要 依賴于抽象接口,不要依賴于具體實現。 簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就降低了客戶與實現模塊間的耦合。
bad case: Driver強依賴于奔馳車。
good case:
定義: 接口隔離原則[4],客戶端不應該依賴它不需要的接口。一個類對另一個類的 依賴 應該建立在 最小的接口上 。
bad case: 星探尋找美女的類圖,其中IpettyGirl過于龐大,容納過多可變的因素。
good case: 通過拆分接口,提高了靈活性、可維護性。
定義:迪米特法則[5](Law of Demeter)又叫作 最少知識原則 (The Least Knowledge Principle),一個類對于其他類知道的越少越好,就是說一個對象應當對其他對象有盡可能少的了解,只和朋友通信,不和陌生人說話。
bad case: Teacher要求GroupLeader清點女生的數量,這里Teacher不應該依賴于Gril。
good case:
定義:開閉原則[6],在面向對象編程領域中,規定“軟件中的對象(類,模塊,函數等等)應該對于 擴展是開放 的,但是對于 修改是封閉 的”。
以一個書店售書類圖為例,當在書店要增加一個打折操作時。
bad case:修改實現類,在IBook上增加一個方法GetOffPrice() good case:通過擴展實現變化,增加一個子類OffNovelBook定義一個用于創建對象的接口 Product* CreateProduct() ,讓子類決定實例化哪一個類。工廠方法模式讓類的實例化延遲到子類中進行,從而避免了在父類中創建對象時出現類名稱緊耦合的問題,同時提高了代碼的可擴展性和可維護性。(工廠方法的好處就是 解耦 ,當我們修改了具體的類,對調用方而言完全不用修改)
class Product { // 抽象產品public: virtual void Method() = 0;};class ConcreteProduct1 : public Product {public: void Method() { cout << \"ConcreteProduct1\" << endl; }};class ConcreteProduct2 : public Product {public: void Method() { cout << \"ConcreteProduct2\" << endl; }};class Factory { // 抽象工廠public: virtual Product* CreateProduct() = 0;};class ConcreteFactory1 : public Factory {public: Product* CreateProduct() {return new ConcreteProduct1(); }};class ConcreteFactory2 : public Factory {public: Product* CreateProduct() {return new ConcreteProduct2(); }};int main () { Factory *factory1 = new ConcreteFactory1(); Factory *factory2 = new ConcreteFactory2(); Product *product1 = factory1->CreateProduct(); Product *product2 = factory2->CreateProduct(); product1->Method(); product2->Method();}
為創建一組相關或相互依賴的對象提供一個接口,而且無須指定他們的具體類。(工廠方法模式針對的是一個產品等級結構;而抽象工廠模式針對的是 多個產品等級結構 。抽象工廠模式主要用來實現生產一系列的產品。)
class AbstractProductA { public: virtual ~AbstractProductA(){}; virtual std::string FunctionA() const = 0;};class ProductA1 : public AbstractProductA { public: std::string FunctionA() const override { return \"The result of the product A1.\"; }};class ProductA2 : public AbstractProductA { std::string FunctionA() const override { return \"The result of the product A2.\"; }};class AbstractProductB { public: virtual ~AbstractProductB(){}; virtual std::string FunctionB() const = 0;};class ProductB1 : public AbstractProductB { public: std::string FunctionB() const override { return \"The result of the product B1.\"; }};class ProductB2 : public AbstractProductB { public: std::string FunctionB() const override { return \"The result of the product B2.\"; }};class AbstractFactory { public: virtual AbstractProductA *CreateProductA() const = 0; virtual AbstractProductB *CreateProductB() const = 0;};class Factory1 : public AbstractFactory { public: AbstractProductA *CreateProductA() const override { return new ProductA1(); } AbstractProductB *CreateProductB() const override { return new ProductB1(); }};class Factory2 : public AbstractFactory { public: AbstractProductA *CreateProductA() const override { return new ProductA2(); } AbstractProductB *CreateProductB() const override { return new ProductB2(); }};void Client(const AbstractFactory &factory) { const AbstractProductA *productA = factory.CreateProductA(); const AbstractProductB *productB = factory.CreateProductB(); std::cout << productA->FunctionA() << \"
\"; std::cout << productB->FunctionB() << \"
\"; delete productA; delete productB;}int main() { Factory1 *f1 = new Factory1(); Client(*f1); delete f1; Factory2 *f2 = new Factory2(); Client(*f2); delete f2; return 0;}
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。(建造者模式關注的是 零件類型 和裝配工藝( 順序 ))
class Product1{public: std::vectormParts; void ListParts()const{ std::cout << \"Product parts: \"; for (size_t i=0;imProduct->mParts.push_back(\"PartA1\"); } void ProducePartB()const override{ this->mProduct->mParts.push_back(\"PartB1\"); } void ProducePartC()const override{ this->mProduct->mParts.push_back(\"PartC1\"); } Product1* GetProduct() { Product1* result= mProduct; Reset(); return result; }};class Director { Builder* mbuilder;public: void set_builder(Builder* builder){ mbuilder = builder; } void BuildMinimalViableProduct(){ mbuilder->ProducePartA(); } void BuildFullFeaturedProduct(){ mbuilder->ProducePartA(); mbuilder->ProducePartB(); mbuilder->ProducePartC(); }};void ClientCode(Director& director){ ConcreteBuilder1* builder = new ConcreteBuilder1(); director.set_builder(builder); std::cout << \"Standard basic product:
\"; director.BuildMinimalViableProduct(); Product1* p= builder->GetProduct(); p->ListParts(); delete p; std::cout << \"Standard full featured product:
\"; director.BuildFullFeaturedProduct(); p= builder->GetProduct(); p->ListParts(); delete p; // Remember, the Builder pattern can be used without a Director class. std::cout << \"Custom product:
\"; builder->ProducePartA(); builder->ProducePartC(); p=builder->GetProduct(); p->ListParts(); delete p; delete builder;}int main(){ Director* director= new Director(); ClientCode(*director); delete director; return 0; }
用原型實例指定創建對象的種類,并且通過 拷貝 這些原型創建新的對象。(原型模式實現的是一個Clone 接口,注意是接口,也就是基于 多態的 Clone 虛函數 。)
class Prototype { protected: string mPrototypeName; float mPrototypeField;public: Prototype() {} Prototype(string prototypeName) : mPrototypeName(prototypeName) { } virtual ~Prototype() {} virtual Prototype *Clone() const = 0; virtual void Function(float prototype_field) { this->mPrototypeField = prototype_field; std::cout << \"Call Function from \" << mPrototypeName << \" with field : \" << prototype_field << std::endl; }};class ConcretePrototype1 : public Prototype {private: float mConcretePrototypeField;public: ConcretePrototype1(string prototypeName, float concretePrototypeField) : Prototype(prototypeName), mConcretePrototypeField(concretePrototypeField) { } Prototype *Clone() const override { return new ConcretePrototype1(*this); }};class ConcretePrototype2 : public Prototype {private: float mConcretePrototypeField;public: ConcretePrototype2(string prototypeName, float concretePrototypeField) : Prototype(prototypeName), mConcretePrototypeField(concretePrototypeField) { } Prototype *Clone() const override { return new ConcretePrototype2(*this); }};class PrototypeFactory {private: std::unordered_map>mPrototypes;public: PrototypeFactory() { mPrototypes[Type::PROTOTYPE_1] = new ConcretePrototype1(\"PROTOTYPE_1 \", 50.f); mPrototypes[Type::PROTOTYPE_2] = new ConcretePrototype2(\"PROTOTYPE_2 \", 60.f); } ~PrototypeFactory() { delete mPrototypes[Type::PROTOTYPE_1]; delete mPrototypes[Type::PROTOTYPE_2]; } Prototype *CreatePrototype(Type type) { return mPrototypes[type]->Clone(); }};void Client(PrototypeFactory &prototypeFactory) { std::cout << \"Let"s create a Prototype 1
\"; Prototype *prototype = prototypeFactory.CreatePrototype(Type::PROTOTYPE_1); prototype->Function(90); delete prototype; std::cout << \"Let"s create a Prototype 2
\"; prototype = prototypeFactory.CreatePrototype(Type::PROTOTYPE_2); prototype->Function(10); delete prototype;}int main() { PrototypeFactory *prototypeFactory = new PrototypeFactory(); Client(*prototypeFactory); delete prototypeFactory; return 0;}
單例模式是指在整個系統生命周期內,保證 一個類只能產生一個實例 ,確保該類的 唯一性 。
剩余60%,完整內容請點擊下方鏈接查看:
阿里云開發者社區,千萬開發者的選擇。百萬精品技術內容、千節免費系統課程、豐富的體驗場景、活躍的社群活動、行業專家分享交流,盡在:
關鍵詞: