999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

模板方法設(shè)計模式的泛型編程技術(shù)實現(xiàn)

2019-07-08 03:44:41余建華趙曉蓮
計算機時代 2019年5期

余建華 趙曉蓮

摘? 要: 模板方法是設(shè)計模式中一種典型的設(shè)計范式,傳統(tǒng)上是利用面向?qū)ο缶幊碳夹g(shù)的多態(tài)屬性實現(xiàn)的,文章應(yīng)用泛型編程技術(shù)來實現(xiàn)模板方法設(shè)計模式。這種實現(xiàn)方式舍棄了面向?qū)ο缶幊碳夹g(shù)中基于繼承的基類,派生類的虛函數(shù)機制,免去了在程序運行過程中虛函數(shù)二次尋址的代價。在保留設(shè)計模式中程序修改擴展彈性的同時,降低了程序運行負(fù)載,提高運行速度,展現(xiàn)出一種泛型編程技術(shù)不同于傳統(tǒng)的應(yīng)用場景。

關(guān)鍵詞: 面向?qū)ο缶幊? 泛型編程; 模板函數(shù); 模板方法; 設(shè)計模式

中圖分類號:TP311.1? ? ? ? ? 文獻(xiàn)標(biāo)志碼:A? 文章編號:1006-8228(2019)05-41-05

Abstract: The template method is a representative pattern in design patterns. Traditionally, it is implemented by polymorphic attributes of object oriented programming technology. This paper introduces a method that implements the template method pattern by generic programming. This method of implementation abnegates the inheritance based virtual function mechanism which is the pivotal conception in object oriented programming, and avoids the expense for the second function addressing of virtual function in program running. The template method pattern implemented by generic programming not only reserves the flexibility for program extending and amending, but also improves the speed of program executing, demonstrating another scene of application of generic programming which is different from the traditional.

Key words: object oriented; generic programming; template function; template method pattern; design patterns

0 引言

泛型編程技術(shù)及在其上發(fā)展的模板元編程是C++編程領(lǐng)域近年來最為關(guān)注的課題。模板是實現(xiàn)泛型編程技術(shù)的關(guān)鍵性C++構(gòu)件[1]。模板第一次具有里程碑意義的應(yīng)用是標(biāo)準(zhǔn)模板程序庫STL,其通過泛型容器、迭代器、泛型算法實現(xiàn),富有彈性,包含數(shù)據(jù)結(jié)構(gòu)和算法的可復(fù)用組件庫可擴展,淋漓盡致地向我們展現(xiàn)了模板的使用藝術(shù),以至于我們一提到模板,首先想到的就是實現(xiàn)泛型容器的技術(shù)。實際上模板技術(shù)的魅力遠(yuǎn)不止于此,利用其具有的編譯期計算能力而發(fā)展的模板元編程技術(shù),以及其與設(shè)計模式的結(jié)合,為我們打開了泛型編程領(lǐng)域的一片新天地。 設(shè)計模式是早先C++編程領(lǐng)域的專家為幫助應(yīng)用開發(fā)者針對一些常見的,特定的應(yīng)用問題而歸納總結(jié)的一組可復(fù)用的設(shè)計范式[3]。模板方法是設(shè)計模式中一種典型的行為型模式。本文首先介紹傳統(tǒng)利用面向?qū)ο缶幊碳夹g(shù)的多態(tài)屬性實現(xiàn)的方式,然后應(yīng)用泛型編程技術(shù)實現(xiàn)模板方法設(shè)計模式,最后闡述兩種實現(xiàn)的差異。

1 面向?qū)ο蠹夹g(shù)實現(xiàn)模板方法

模板方法是一種行為型的設(shè)計模式,主要思想是在基類中定義功能單元或算法的骨架,而這個骨架使用的細(xì)節(jié)操作延遲到派生類實現(xiàn)。在不改變骨架的條件下,通過某些細(xì)節(jié)操作步驟的變更,我們可以方便地維護(hù),擴展功能單元或算法。

例如我們想計算封閉幾何圖形的面積與周長比率,以此來發(fā)現(xiàn)何種圖形的單位周長圍成的面積最大。

首先定義一個幾何圖形基類:

class Geometrics

{ public:

float CalculateRatio0Area2Circularity(void);

private:

virtual float CalculatePerimeter(void)=0;

virtual float CalculateArea(void)=0;

};

基類的計算面積與周長比率的公有成員函數(shù)用來實現(xiàn)算法的骨架,其主要是調(diào)用計算周長和面積的純虛函數(shù)來算出幾何圖形的周長和面積,然后算出比率。

float Geometrics::CalculateRatio0Area2Circularity(void)

{ float fPerimeter=1.0,fArea=1.0;

fPerimeter=CalculatePerimeter();

fArea=CalculateArea();

return(fArea/fPerimeter);

}

定義一個圓的子類,用以實際計算圓的面積與周長比率。

class Circularity: public Geometrics

{ public:

Circularity(int iRadius):m_iRadius(iRadius){};

private:

float CalculatePerimeter(void);

float CalculateArea(void);

private:

int m_iRadius;

};

圓形子類實現(xiàn)基類的計算周長和面積的純虛函數(shù),用以具體計算圓形的周長和面積。

float Circularity::CalculatePerimeter()

{ return 2*PI*m_iRadius; }

float Circularity::CalculateArea()

{ return PI*m_iRadius*m_iRadius; }

同樣定義一個矩形的子類,用以實際計算矩形的面積與周長比率

class Rectangle:public Geometrics

{ public:

Rectangle(int iLength, int iWidth):m_length(iLength),

m_width(iWidth) {};

private:

float CalculatePerimeter(void);

float CalculateArea(void);

private:

int m_length;

int m_width;

};

矩形子類實現(xiàn)基類的計算周長和面積的純虛函數(shù),用以具體計算矩形的周長和面積

float Rectangle::CalculatePerimeter()

{ return 2*(m_length+m_width); }

float Rectangle::CalculateArea()

{ return m_length * m_width; }

主函數(shù)調(diào)用基類對象使用計算圓和矩形面積與周長比率的功能。注意生成的是派生類對象,指針卻是基類對象類型。

int main()

{ class Geometrics *pGeometrics01=new Circularity(3);

class Geometrics *pGeometrics02=new Rectangle(3,3);

std::cout<CalculateRatio0Area2Circularity() << std::endl;

std::cout<CalculateRatio0Area2Circularity()<

return 0;

}

使用模板方法,我們可以方便地擴展或修改。如通過增加其他圖形的子類,計算其他圖形的面積與周長比率,并不需要再定義面積與周長比率的計算方法;或者修改某一圖形面積與周長的計算方法,也不影響其他已有圖形面積與周長的計算。

2 泛型編程技術(shù)實現(xiàn)模板方法

通過泛型編程技術(shù)也能實現(xiàn)模板方法設(shè)計模式的功能。

定義一個函數(shù)模板,用以實現(xiàn)計算面積與周長比率的算法骨架。

template

float CalculateRatio0Area2Circularity(const T& tGeometrics)

{ float fPerimeter=1.0,fArea=1.0;

fPerimeter=tGeometrics.CalculatePerimeter();

fArea=tGeometrics.CalculateArea();

return(fArea/fPerimeter);

}

定義一個圓形類,用以實際計算圓的面積與周長比率,注意這里不再有繼承關(guān)系。

class Circularity

{ public:

Circularity(int iRadius):m_iRadius(iRadius){};

float CalculatePerimeter(void) const;

float CalculateArea(void) const;

private:

int m_iRadius;

};

圓形類實現(xiàn)計算周長和面積的成員函數(shù),用以具體計算圓形的周長和面積

float Circularity::CalculatePerimeter() const

{ return 2*PI*m_iRadius; }

float Circularity::CalculateArea() const

{ return PI*m_iRadius*m_iRadius; }

定義一個矩形類,用以實際計算矩形的面積與周長比率。

class Rectangle

{ public:

Rectangle(int iLength, int iWidth):m_length(iLength),

m_width(iWidth) {};

float CalculatePerimeter(void) const;

float CalculateArea(void) const;

private:

int m_length;

int m_width;

};

矩形類實現(xiàn)計算周長和面積的成員函數(shù),用以具體計算矩形的周長和面積

float Rectangle::CalculatePerimeter() const

{ return 2*(m_length + m_width); }

float Rectangle::CalculateArea() const

{ return m_length * m_width; }

主函數(shù)調(diào)用函數(shù)模板使用計算圓和矩形面積與周長比率的功能。

int main()

{ class Circularity stCircularity01(3);

class Rectangle stRectangle01(3,3);

std::cout<<"Circularity:"

<(stCircularity01) << std::endl;

std::cout<<"Rectangle:"

<(stRectangle01) << std::endl;

return 0;

}

3 面向?qū)ο蠹夹g(shù)與泛型編程技術(shù)的復(fù)合應(yīng)用

我們舉例的這個計算幾何圖形的面積與周長比率的問題,在實現(xiàn)算法上分成了兩個層次。第一層是利用計算出來的面積與周長相除,計算比率。第二層是計算具體幾何圖形的面積與周長。第一層是共性操作,第二層是特性操作。

實現(xiàn)這個算法的第一個方法是設(shè)計模式中的模板方法。將第一層共性操作放到基類成員函數(shù)中作為實現(xiàn)方法的骨架,將第二層特性操作放到派生類成員函數(shù),實現(xiàn)這個骨架使用的細(xì)節(jié)操作。這種基于C++繼承和虛擬函數(shù)機制的變化由用戶使用基類類型的指針來調(diào)用虛擬函數(shù)來支持。正是因為不管實際上生成哪一個派生類對象,在使用形式上都是基類指針,編譯期無法決定實際調(diào)用對象的成員函數(shù),此任務(wù)由執(zhí)行期獲得對象的實際派生類型后決定,因此這種機制的彈性變化稱之為動態(tài)多態(tài)[2]。

實現(xiàn)這個算法的第二個方法是泛型編程的模板技術(shù)。通過模板函數(shù)的表達(dá)式及具體操作,我們在模板和將要用以具現(xiàn)模板的參數(shù)間約定了一組接口,所有具現(xiàn)模板的參數(shù)類型都要實現(xiàn)這些接口。這些接口就是抽象出來的所有參數(shù)類型的共性操作。把這些共性操作放置于模板中,把細(xì)節(jié)實現(xiàn)的特性操作放置于具體類型的成員函數(shù)中,我們同樣實現(xiàn)了解決方法模型的兩層結(jié)構(gòu),由此獲得同樣的設(shè)計彈性。由于具體使用的對象類型在編譯期具現(xiàn)化模板函數(shù)時就已確定,因此這種基于模板技術(shù)實現(xiàn)的彈性變化稱之為靜態(tài)多態(tài)[5]。

現(xiàn)在我們來個“動”,“靜”結(jié)合,把設(shè)計模式中的模板方法和泛型編程中的模板技術(shù)復(fù)合起來產(chǎn)生一個解決問題的方法模型用以解決更復(fù)雜的問題,同時擁有更高的彈性。為此我們把舉的例子修改一下,有計算基礎(chǔ)幾何圖形的面積與周長比率改為組合幾何圖形的面積與周長比率。這種組合有兩種方式,凸型和凹型,如圖1所示。

我們解決問題的算法模型結(jié)構(gòu)分為三個層次。如圖2所示。

第一層是計算幾何圖形的面積與周長比率,如果比率的算法有修改需求,將在這里修改。注意這里的修改將影響所有圖形比率的計算,這是共性層。我們用函數(shù)模板實現(xiàn)這一層。

template

float CalculateRatio0Area2Circularity(T& tGeometrics)

{ float fPerimeter=1.0,fArea=1.0;

fPerimeter=tGeometrics.CalculatePerimeter();

fArea=tGeometrics.CalculateArea();

return(fArea/fPerimeter);

}

第二層是計算“凸” 或 “凹” 組合圖形的面積與周長。我們分別定義兩個基類管理計算。如果想要擴展計算其他組合方式的組合圖形,可以在這一層擴展新基類,這是偏特性層(借用泛型編程術(shù)語)。

凸組合圖形基類的定義:

class Convexity

{ public:

float CalculatePerimeter(void);

float CalculateArea(void);

private:

virtual float CalculatePerimeterPolygonA(void)=0;

//const;

virtual float CalculatePerimeterPolygonB(void)=0;

virtual float CalculateAreaPolygonA(void)=0;

virtual float CalculateAreaPolygonB(void)=0;

};

凸組合圖形計算面積與周長:

float Convexity::CalculatePerimeter(void)

{ float fPerimeterPolygonA, fPerimeterPolygonB;

fPerimeterPolygonA=CalculatePerimeterPolygonA();

fPerimeterPolygonB=CalculatePerimeterPolygonB();

return fPerimeterPolygonA + fPerimeterPolygonB;

}

float Convexity::CalculateArea(void)

{ float fAreaPolygonA, fAreaPolygonB;

fAreaPolygonA=CalculateAreaPolygonA();

fAreaPolygonB=CalculateAreaPolygonB();

return fAreaPolygonA+fAreaPolygonB;

}

⑴ 凹組合圖形基類的定義與凸組合圖形基類類似;

⑵ 凹組合圖形計算周長的方法與凸組合圖形基類相同,凹組合圖形計算面積的方法與凸組合圖形基類類似,前者組成組合圖形的子圖形相減,后者是相加,此處不再列出;

⑶ 第三層是計算具體組合圖形的面積與周長,也是面積與周長的實際計算點。如果“凸” 或 “凹” 組合圖形由其他基礎(chǔ)圖形構(gòu)成,可在這一層擴展,這是特性層。我們用派生類來管理計算。

由圓與矩形組成的凸組合圖形類定義:

class ConvexityConcreteA: public Convexity

{ public:

ConvexityConcreteA(int iRadius, int iLength):

m_iRadius(iRadius), m_iLength(iLength) {};

private:

virtual float CalculatePerimeterPolygonA(void);

virtual float CalculatePerimeterPolygonB(void);

virtual float CalculateAreaPolygonA(void);

virtual float CalculateAreaPolygonB(void);

private:

int m_iRadius;

int m_iLength;

};

由圓與矩形組成的凸組合圖形面積與周長的計算:

float ConvexityConcreteA::CalculatePerimeterPolygonA(void)

{ return 2*(m_iLength + m_iRadius); }

float ConvexityConcreteA::CalculatePerimeterPolygonB(void)

{ return PI*m_iRadius; }

float ConvexityConcreteA::CalculateAreaPolygonA(void)

{ return 2*m_iRadius * m_iLength; }

float ConvexityConcreteA::CalculateAreaPolygonB(void)

{ return 0.5*PI*pow(m_iRadius, 2); }

由圓與三角形組成的凸組合圖形類定義:

class ConvexityConcreteB: public Convexity

{ public:

ConvexityConcreteB(int iHigh, int iLength, int

iWidth):m_iHigh(iHigh), m_iLength(iLength),

m_iWidth(iWidth){};

private:

virtual float CalculatePerimeterPolygonA(void);

virtual float CalculatePerimeterPolygonB(void);

virtual float CalculateAreaPolygonA(void);

virtual float CalculateAreaPolygonB(void);

private:

int m_iHigh;

int m_iLength;

int m_iWidth;

};

由圓與三角形組成的凸組合圖形面積與周長的計算:

float ConvexityConcreteB::CalculatePerimeterPolygonA(void)

{ return 2*m_iLength + m_iWidth; }

float ConvexityConcreteB::CalculatePerimeterPolygonB(void)

{ return 2*sqrt(pow(0.5*m_iWidth, 2)+pow(m_iHigh, 2)); }

float ConvexityConcreteB::CalculateAreaPolygonA(void)

{ return m_iLength * m_iWidth; }

float ConvexityConcreteB::CalculateAreaPolygonB(void)

{ return 0.5*m_iWidth*m_iHigh; }

由圓與矩形組成的凹組合圖形類定義與相應(yīng)的凸組合圖形定義類似,其組成的凹組合圖形面積與周長的計算與相應(yīng)的凸組合圖形面積與周長計算類似;

由圓與三角形組成的凹組合圖形類定義與相應(yīng)的凸組合圖形定義類似,其組成的凹組合圖形面積與周長的計算與相應(yīng)的凸組合圖形面積與周長計算類似,此處不再列出。

在主函數(shù)中,我們用模板函數(shù)來獲取各個組合圖形的面積與周長比率。

int main()

{ class ConvexityConcreteA stConvexityConcreteA(2,4);

class ConvexityConcreteB stConvexityConcreteB(2,4,4);

class ConcavityConcreteA stConcavityConcreteA(2,4);

class ConcavityConcreteB stConcavityConcreteB(2,4,4);

std::cout<<"ConvexityConcreteA:"

<(stConvexityConcreteA) << std::endl;

std::cout<<"ConvexityConcreteB:"

<(stConvexityConcreteB) << std::endl;

std::cout<<"ConcavityConcreteA:"

<(stConcavityConcreteA) << std::endl;

std::cout<<"ConcavityConcreteB:"

<(stConcavityConcreteB) << std::endl;

return 0;

}

4 總結(jié)

模板方法是設(shè)計模式中一種典型的行為型設(shè)計范式[6],在設(shè)計模式中是利用面向?qū)ο缶幊碳夹g(shù)中基于繼承的基類,派生類的虛函數(shù)機制來實現(xiàn)的。本文應(yīng)用泛型編程技術(shù)來實現(xiàn)模板方法設(shè)計模式。這種實現(xiàn)方式是利用的是模版函數(shù)與實現(xiàn)參數(shù)間的約定接口[4],在接口的定義域?qū)崿F(xiàn)過程中獲得與設(shè)計模式同樣的設(shè)計彈性,同時省去了虛函數(shù)運行期多態(tài)的動態(tài)開銷,降低了運行負(fù)載,展現(xiàn)出一種泛型編程技術(shù)不同于傳統(tǒng)的應(yīng)用場景。

參考文獻(xiàn)(References):

[1] Stanley B·Lippman,Josée Lajoie . C++ Primer 中文版(第三版)[M].電子工業(yè)出版社,2013.

[2] Bruce Eckel.C++編程思想(第二版)[M].機械工業(yè)出版社,2002.

[3] Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides.設(shè)計模式 可復(fù)用面向?qū)ο筌浖幕A(chǔ)[M].機械工業(yè)出版社,2000.

[4] Andrei Alexandrescu. Modern C++ Design[M].Addison-Wesley Professional,2003.

[5] David Vandevoorde,Nicolai M.Josuttis. C++Templates中文版[M].人民郵電出版社,2008.

[6] 結(jié)城浩.圖解設(shè)計模式[M].人民郵電出版社,2016.

主站蜘蛛池模板: 色综合中文综合网| 亚洲人成网址| 国产毛片片精品天天看视频| 国产欧美精品一区二区| 一级毛片中文字幕| 狠狠五月天中文字幕| 很黄的网站在线观看| 午夜日b视频| 麻豆精品在线| 国产第一页免费浮力影院| 日本尹人综合香蕉在线观看| 欧美另类精品一区二区三区| 99久久精品久久久久久婷婷| 九九热免费在线视频| 国产精品白浆无码流出在线看| 欧美精品在线视频观看| 久久精品无码一区二区日韩免费| 国产福利在线观看精品| 欧美成在线视频| 色天堂无毒不卡| 美女国产在线| 日韩av在线直播| 一级成人a毛片免费播放| 欧美一区二区三区国产精品| 9966国产精品视频| 国产日本欧美在线观看| 成人久久精品一区二区三区| 波多野结衣亚洲一区| 久久a毛片| 女人18毛片久久| 热这里只有精品国产热门精品| 国产成人午夜福利免费无码r| 国产成人精品免费视频大全五级| 国产18在线| 国产一级裸网站| 中文字幕亚洲精品2页| 国产精品视频公开费视频| 影音先锋丝袜制服| a毛片在线免费观看| 一本色道久久88| 成人一区在线| 国产真实二区一区在线亚洲| 国产成人调教在线视频| 国产欧美日韩18| 精品久久蜜桃| 国产一区自拍视频| 亚洲第一中文字幕| 色吊丝av中文字幕| 国产成人做受免费视频| 97色婷婷成人综合在线观看| 国产成人久久综合777777麻豆| 亚洲第一极品精品无码| 成人在线观看不卡| 日韩免费无码人妻系列| 国产主播在线观看| 精品国产Ⅴ无码大片在线观看81| 欧美一级在线看| 亚洲精品天堂在线观看| 亚洲视频影院| 中文字幕亚洲另类天堂| 国产主播在线一区| 毛片一级在线| 3p叠罗汉国产精品久久| 亚洲一区无码在线| 日韩欧美在线观看| 亚洲欧州色色免费AV| 99精品这里只有精品高清视频| 毛片免费网址| 国产欧美成人不卡视频| 欧美高清日韩| 欧美视频在线播放观看免费福利资源 | 亚洲最新地址| 国产亚洲精| 伊伊人成亚洲综合人网7777| 香蕉久久国产精品免| 国产人碰人摸人爱免费视频| 国产欧美日韩专区发布| 久久公开视频| 亚洲最大福利视频网| 日韩精品无码一级毛片免费| 国产精品熟女亚洲AV麻豆| 午夜视频免费试看|