首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

設計模式之旅:以 C++ Template 改良策略模式

     編輯:關於C#

背景

前文使用策略模式讓 Grapher 繪製三角形、圓形、正方形。後來需求變更,希望在形狀中繪製文字。

策略模式初始類別圖

執行結果預期:

Draw Hello Shape!! in Square
Draw Hello C++!! in Circle

傳遞 this 指標的做法

為一勞永逸,將整個物件傳給策略:

class IShape {
public:
 virtual void draw(Grapher &grapher) const = 0;
};

void Grapher::drawShape() {
 this->shape->draw(*this);
}

完整程式碼:

傳遞 this 指標版類別圖
/**/*
 (C) OOMusou 2007 https://oomusou.cnblogs.com

Filename : DP_StrategyPattern3_polymorphism_this.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to use Strategy Pattern with *this
Release : 04/04/2007 1.0
*/
#include <iostream>
#include <string>

using namespace std;

class Grapher;

class IShape {
public:
 virtual void draw(Grapher &grapher) const = 0;
};

class Grapher {
private:
 IShape *shape;
 string text;

public:
 Grapher() {}
 Grapher(IShape *shape, const char *text = "Hello Shape!!") : shape(shape), text(string(text)) {}

public:
 void drawShape() {
 this->shape->draw(*this);
 }

 void setShape(IShape *shape, const char* text = "Hello Shape!!") {
 this->text = text;
 this->shape = shape;
 }

 string getText() const {
 return this->text;
 }
};

class Triangle : public IShape {
public:
 void draw(Grapher &grapher) const {
 cout << "Draw " << grapher.getText() << " in Triangle" << endl;
 }
};

class Circle : public IShape {
public:
 void draw(Grapher &grapher) const {
 cout << "Draw " << grapher.getText() << " in Circle" << endl;
 }
};

class Square : public IShape {
public:
 void draw(Grapher &grapher) const {
 cout << "Draw " << grapher.getText() << " in Square" << endl;
 }
};

int main() {
 Grapher theGrapher(&Square());
 theGrapher.drawShape();

 theGrapher.setShape(&Circle(), "Hello C++!!");
 theGrapher.drawShape();
}

執行結果:

Draw Hello Shape!! in Square
Draw Hello C++!! in Circle

問題:過度耦合

IShape 與 Grapher 緊密相依。若未來有 Painter 類別(與 Grapher 無繼承關係)想復用策略,此設計無法支援。

以 Template 解耦

使用泛型取代具體型別:

template <typename T>
class IShape {
public:
 virtual void draw(T &grapher) const = 0;
};

完整程式碼:

Template 版類別圖
/**/*
 (C) OOMusou 2007 https://oomusou.cnblogs.com

Filename : DP_StrategyPattern3_template_this.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to use Strategy Pattern with *this by template
Release : 04/03/2007 1.0
*/
#include <iostream>
#include <string>

using namespace std;

class Grapher;

template <typename T>
class IShape {
public:
 virtual void draw(T &grapher) const = 0;
};

class Grapher {
private:
 IShape<Grapher> *shape;
 string text;

public:
 Grapher() {}
 Grapher(IShape<Grapher> *shape, const char* text = "Hello Shape!!") : shape(shape), text(string(text)) {}

public:
 void drawShape() {
 this->shape->draw(*this);
 }

 void setShape(IShape<Grapher> *shape, const char* text = "Hello Shape!!") {
 this->text = text;
 this->shape = shape;
 }

 string getText() const {
 return this->text;
 }
};

template <typename T>
class Triangle : public IShape<T> {
public:
 void draw(T &grapher) const {
 cout << "Draw " << grapher.getText() << " in Triangle" << endl;
 }
};

template <typename T>
class Circle : public IShape<T> {
public:
 void draw(T &grapher) const {
 cout << "Draw " << grapher.getText() << " in Circle" << endl;
 }
};

template <typename T>
class Square : public IShape<T> {
public:
 void draw(T &grapher) const {
 cout << "Draw " << grapher.getText() << " in Square" << endl;
 }
};

int main() {
 Grapher theGrapher(&Square<Grapher>());
 theGrapher.drawShape();

 theGrapher.setShape(&Circle<Grapher>(), "Hello C++!!");
 theGrapher.drawShape();
}

執行結果:

Draw Hello Shape!! in Square
Draw Hello C++!! in Circle

結語

泛型應用廣泛,此例僅為小試身手。在 OOP 世界中使用策略模式時,常傳遞 *this 給策略,搭配泛型程式設計 (GP) 可大幅提升策略的復用程度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved