版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、現(xiàn)代軟件設計技術(shù),潘愛民http://www.icst.pku.edu.cn/CompCourse,內(nèi)容,復習Generic Programming補充一些patterns構(gòu)造框架(framework)的技術(shù)構(gòu)造可重用類庫的技術(shù),復習:creational patters,Factory Method本質(zhì):用一個virtual method完成創(chuàng)建過程Abstract Factory一個product族的factory
2、 method構(gòu)成了一個factory接口Prototype通過product原型來構(gòu)造product,Clone+prototype managerBuilder通過一個構(gòu)造算法和builder接口把構(gòu)造過程與客戶隔離開Singleton單實例類型,如何構(gòu)造這單個實例?如何訪問這單個實例?Finder把對象的獲取過程與客戶隔離開,復習:Structural patterns,Adapter 、bridge、facade
3、adapter用于兩個不兼容接口之間的轉(zhuǎn)接bridge用于將一個抽象與多個可能的實現(xiàn)連接起來facade用于為復雜的子系統(tǒng)定義一個新的簡單易用的接口composite、decorator和proxycomposite用于構(gòu)造對象組合結(jié)構(gòu)decorator用于為對象增加新的職責proxy為目標對象提供一個替代者flyweight針對細粒度對象的一種全局控制手段,復習:Behavioral Patterns,Command
4、 用對象封裝命令,使得命令可以被傳遞、記錄、排隊等Iterator 把對聚合體對象的訪問封裝起來Observer 建立起一對多的通信模型,特別適合于更新通知和事件模型Strategy 把一個對象或者類的某些行為封裝到另一個單獨的對象中Visitor把對一個結(jié)構(gòu)模型的操作單獨組織到一個類中,復習:Behavioral Patterns(續(xù)一),Chain of Responsibility 請求的處理過程,沿著鏈傳遞,
5、decouple發(fā)送方和接收方Interpreter 在類層次結(jié)構(gòu)中,在特定環(huán)境的“interpret”過程Mediator 用一個mediator來decouple各同等單元Memento 在對象之外保存對象的內(nèi)部狀態(tài)State 把一個對象的狀態(tài)獨立出來,動態(tài)可變換狀態(tài)對象的類型Template Method 在基類中定義算法的骨架,把某些細節(jié)延遲到子類中,復習:Behavioral Patterns(續(xù)二),St
6、rategy、Iterator、Mediator、State、command用一個對象來封裝某些特性,比如變化、交互、狀態(tài)、行為、命令Mediator、ObserverObserver建立起subject和observer之間的松耦合連接mediator把約束限制集中起來 -〉中心控制command、Chain of Responsibility、interpretercommand模式側(cè)重于命令的總體管理Chain of
7、 Responsibility側(cè)重于命令被正確處理interpreter用于復合結(jié)構(gòu)中操作的執(zhí)行過程,Generic programming,思想:“通過參數(shù)化技術(shù)達到重用的目的(reuse through parameterization)”,使得組件更容易被定制。實現(xiàn)靜態(tài)配置代碼,從而獲得很高的效率。 Generic Programming可以消除類型和算法之間本來不必要的相依性STL是成功的generic programm
8、ing典型generic programming限制代碼產(chǎn)生的方式:用實體類型代替類型參數(shù),使這些預先編制好的代碼模型成為真正的代碼,無法產(chǎn)生完全新的代碼。,相關(guān)的programming,Aspect-Oriented Programming (AOP) An aspect is a modular unit that cross-cuts the structure of other modular units Aspects
9、 exist in both design and implementation. A design aspect is a modular unit of the design that cross-cuts the structure of other parts of the design. A program or code aspect is a modular unit of the program that cross-
10、cuts other modular units of the program. 把問題分解為功能單元(組件)和aspect在AOP系統(tǒng)中,組件和aspects(交織)組合起來得到一個系統(tǒng)的具體實現(xiàn)。交織組合既可以在compile-time,也可以在runtimeAOSD, 參考:http://aosd.net/,generative programming,Generative Programming 建立起一族軟件系統(tǒng)的模型
11、,在特定的要求下,利用一些基本的、可重用的組件,通過配置,能夠自動根據(jù)需要產(chǎn)生一個高度定制和優(yōu)化的軟件系統(tǒng)實例一些原則用參數(shù)化技術(shù)來概括出差異性對于相依性和交互進行分析和建模通過靜態(tài)鏈接(compile-time)消除不必要的開銷,以及執(zhí)行與特定領(lǐng)域相關(guān)的優(yōu)化將問題空間和方案空間分離,通過配置建立兩者的映射關(guān)系Separation of concerns: borrowed from AOP特點Generative Pr
12、ogramming涉及到軟件開發(fā)過程的各個階段與Domain Engineering結(jié)合A Model-Based Approach:http://www.sei.cmu.edu/domain-engineering/domain_engineering.htmlActive Libraries,C++ Generic Programming,Template技術(shù)使C++成為two-level languagemetaprog
13、ram從科學計算用途-〉一般性的抽象,即generic programming對于編譯器代碼產(chǎn)生、優(yōu)化在編譯時刻,實現(xiàn)靜態(tài)綁定 —— partial evaluation對于庫開發(fā)人員Active libraries,提供一種抽象的功能,并且控制優(yōu)化過程許多技術(shù),如policy(traits)、編譯時刻計算功能對于應用開發(fā)人員定制template class或者template function,C++ Generi
14、c Programming(續(xù)),設計思想編譯時刻程序設計,類似于logic-programming即,在compile-time讓編譯器完成一些功能,例如靜態(tài)的計算功能if/else,loop,switch對type進行一些基本的邏輯操作(編程)保證類型安全寧可要compile-time error,也不要runtime error盡可能地泛化 —— 抽象性跟傳統(tǒng)的設計方法結(jié)合起來,比如利用patterns,Temp
15、late基礎(chǔ) —— class template,templateclass Array {public:T& operator[](size_t n) {if (n =MAX_ELEMS) throw "Out of bounds! ";return m_rg[n];}protected:T m_rg[MAX_ELEMS];};,使用:Array a1;Array a2;,Tem
16、plate基礎(chǔ) —— 模板特化template specialization,templateclass Array {public:char& operator[](size_t n) {if (n =256) throw "Out of bounds!";return m_sz[n];}bool operator== (const Array& rhs) {re
17、turn strcmp(m_sz, rhs.m_sz) == 0;}protected:char m_sz[256];};,Template基礎(chǔ) —— 部分模板特化 partial template specialization,templateclass Array {public:T& operator[](size_t n) {if (n =MAX_ELEMS) throw "Out
18、of bounds!";return m_sz[n];}bool operator== (const Array& rhs) {return strcmp(m_sz, rhs.m_sz) == 0;}protected:T m_sz[MAX_ELEMS];};*Visual C++ 6不支持部分模板特化,Template基礎(chǔ) —— 函數(shù)模板function template,temp
19、late void Swap(T &a, T&b){ T temp = a ; a = b; b = temp;}template T& min(T& a, T& b){ return a < b ? a : b; },模板參數(shù),compile-time起作用,函數(shù)參數(shù),runtime
20、起作用,Template基礎(chǔ) —— 函數(shù)對象泛化generalized functors(function objects),functor:重載了operator()的C++對象,擴展了函數(shù)指針的概念,可以增加內(nèi)部狀態(tài),可以被當作對象來傳遞,具有值語義(value semantic)。它可以是template class,也可以不是template class Functor{public :ResultType o
21、perator()();// other member functionprivate :// implementation};用法:Functor MyFunctor(val1);int Result = MyFunctor();,Template技術(shù) —— 代替runtime的if/else,// Class declarationstemplateclass ConditionProcess { };c
22、lass ConditionProcess {public: static inline void f() { statement1; } // true case};class ConditionProcess {public: static inline void f() { statement2; } // false case};// Repla
23、cement for 'if/else' statement:ConditionProcess ::f();,if (condition) statement1;else statement2;,,Compile-time能夠確定condition的值,Template技術(shù) —— 代替runtime的switch,// Class declarationstemplateclass Switc
24、hProcess {public: static inline void f() { default-statement; }};class SwitchProcess {public: static inline void f() { statement1; }};class SwitchProcess {public: static inline void f() { statemen
25、t2; }};// Replacement for switch(i) statementSwitchProcess ::f();,int i;switch(i){ case value1: statement1; break; case value2: statement2; break; default: defau
26、lt-statement; break;},,Template技術(shù) —— 代替runtime的do循環(huán),templateclass DoProcess {private: enum { go = (I-1) != 0 };public: static inline void f() { statement; DoProcess ::f(); }};//
27、Specialization provides base case for recursionclass DoProcess {public: static inline void f() { }};// Equivalent loop codeDoProcess ::f();,int i = N;do { statement;} while (--i > 0);,,Template技術(shù) ——
28、代替runtime的臨時變量,templateclass countBits { enum { bit3 = (N & 0x08) ? 1 : 0, bit2 = (N & 0x04) ? 1 : 0, bit1 = (N & 0x02) ? 1 : 0, bit0 = (N & 0x01) ? 1 : 0
29、 };public: enum { nbits = bit0+bit1+bit2+bit3 }; };int i = countBits::nbits;,int countBits(int N){ int bit3 = (N & 0x08) ? 1 : 0, bit2 = (N & 0x04) ? 1 : 0, bit1 = (N & 0x02)
30、? 1 : 0, bit0 = (N & 0x01) ? 1 : 0; return bit0+bit1+bit2+bit3;}int i = countBits(13);,,Template技術(shù) —— 計算 Compile-time functions,一般原則:局部變量用enum類型循環(huán)轉(zhuǎn)化為遞歸,結(jié)束條件為一個特化版本也可以是多重循環(huán),需要用到部分特化特性條件分支用模板特化解決效
31、果:以類型為基礎(chǔ),實現(xiàn)各種操作例如sin x = x - x^3/3! + x^5/5! - x^7/7! + …在編譯時刻求pow(x,y),即x的y次方,Template技術(shù) —— 計算pow(x,y),templatestruct ctime_pow {enum { result = X*ctime_pow::result };};templatestruct ctime_pow{enum { resu
32、lt = 1};};用法:const int z = ctime_pow::result;,Trait技術(shù),定義一些“函數(shù)”,這些函數(shù)的參數(shù)和返回值都是類型(type),而不是數(shù)據(jù)(data)例如:對于一個數(shù)組類,它的元素類型和平均數(shù)的類型不一定相同,可以用一個trait class來建立這種映射關(guān)系對應關(guān)系A(chǔ)verage_type(T) -> TAverage_type(int) -> float
33、Trait的使用:Average的實現(xiàn),Partial evaluation,一個程序的計算分為兩個部分靜態(tài)計算:在編譯時刻執(zhí)行動態(tài)計算:在運行時刻執(zhí)行例如,計算立方體的體積,Template技術(shù) —— 模板類作為基類,某種程度上可以代替模板特化templateclass String : public Array {public :// additional functionalitybool operator
34、==(const String& rhs) {return strcmp(m_rg, rhs.m_rg) ==0;}},Template技術(shù) —— 以模板參數(shù)作為基類,允許用戶把自己的類插入到類層次的中間用戶提供基類,類庫使用基類templateclass Deriving : public Base {……},C++ as a two-level language,將type當作first-clas
35、s value來對待例如一種做法: 下面的句子typedef T T_average;相當于typedef T_average = T;實現(xiàn)了類型的賦值,Template技術(shù) —— typelistfrom 《Modern C++ Design》,以類型作為元素構(gòu)成鏈 template struct Typelist { typedef T Head; typedef U
36、 Tail; };,例如Length操作 template struct Length; template struct Length { enum { value = 0 }; }; template struct Length > { enum { v
37、alue = 1 + Length::value }; };,typelist各種操作LengthTypeAtIndexOfAppendEraseReplaceMostDerived…...,Template技術(shù) —— typelist(續(xù)一),typelist用法#define TYPELIST_1(T1) Typelist#define TYPELIST_2(T1, T2) Typelist#d
38、efine TYPELIST_3(T1, T2, T3) Typelisttemplate class Unit> class GenScatterHierarchy, Unit> : public GenScatterHierarchy , public GenScatterHierarchy{};template class Unit> class G
39、enScatterHierarchy : public Unit{};template class Unit> class GenScatterHierarchy{};,Template技術(shù) —— typelist(續(xù)二),GenScatterHierarchy用法template class Holder{T m_value;};,typedef GenScatterHierarchy My
40、TypeTree,Template技術(shù):動態(tài)綁定 —— 模擬虛函數(shù)多態(tài)性,templateclass Array {public :……virtual int Compare(const Array&rhs)=0;bool operator& rhs){ return this->Compare(rhs) (const Array& rhs){ return this->Co
41、mpare(rhs)> 0; }bool operator==(const Array& rhs){ return this->Compare(rhs) == 0; }},templateclass Array {public :…...bool operator& rhs){ return static_cast(this)->Compare(rhs) (const
42、 Array& rhs){ return static_cast(this)->Compare(rhs) > 0; }bool operator==(const Array& rhs){ return static_cast(this)->Compare(rhs) == 0; }},,policy,Aliases :strategy, behavior class
43、, trait, aspect在設計供重用的類或者組件的時候,盡可能地把細節(jié)抽象出來,雖然這些細節(jié)遍布各處,但它們本身并不構(gòu)成耦合對問題的垂直分解和水平分解,Policy(續(xù)一),想法:用policy來配置一個類或者組件把影響問題的因素分解成幾個不相關(guān)的方面,并且用policy class來表達,例如創(chuàng)建策略線程模型policy之間盡可能不相關(guān)一旦有關(guān)聯(lián),就可能產(chǎn)生一些制約因素,例如引用計數(shù)策略(RefCountPolic
44、y)和存儲策略(StoragePolicy)policy類與host類之間可以在runtime進行組合,也可以在compile-time進行組合,Policy(續(xù)二),用模板參數(shù)作為policy class編譯器在compile-time對host class進行配置例如:templateclass Widget…… template class CreationPoly>class WidgetManager
45、……,Policy(續(xù)三),Policy組合,用m+n個類組合成n*m種可能,例如:template class CheckingPolicy, template ThreadingModel>class SmartPtr;…… typedef SmartPtr SafeWidgetPtr;templatestruct EnsureNotNull {static void Check(T*& p
46、tr){ if (!ptr) ptr = GetDefaultValue(); }},Policy(續(xù)四),用模板實現(xiàn)Policy的意義在compile-time配置host class,有助于產(chǎn)生更為高效的代碼,更加generic以類為基礎(chǔ)配置一個類,所以policy往往包含靜態(tài)方法,即class-level的方法在設計可重用類或者組件的時候,根據(jù)需要提取出policy,并確定policy的接口實現(xiàn)類似hook的思想,由
47、用戶提供具體的policy class,從而把有些行為往后延遲缺點:要求使用者對于policy有非常的了解,知道每一種策略會影響到問題的哪些方面,Visitor模式(GoF),Visitor模式改進,ConcreteElementAAccept(EleVisitor)OperationA,,ConcreteElementBAccept(EleVisitor)OperationB,,,,EleVisitor,,ElementA
48、Visitor,ElementBVisitor,MyConcreteVisitor,,,,,信息結(jié)構(gòu),Visitor結(jié)構(gòu),Lazy技術(shù),Lazy Initialization,第一次被訪問時初始化Singleton& Singleton::Instance(){if (!pInstance){pInstance = new Singleton;}return *pInstance;}COW(Copy
49、on write),第一次被寫入時才拷貝Lazy Protocol:DCOM協(xié)議,Double-Checked Locking Pattern,假設mutex是一個Mutex對象,現(xiàn)在需要對pInstance的訪問進行同步,一種方案是Singleton& Singleton::Instance(){Lock guard(mutex);if (!pInstance){pInstance = new Singl
50、eton;}return *pInstance;},Double-Checked Locking Pattern(續(xù)一),前述的方案效率比較低,只有一次new操作需要保護,其他的只讀訪問不必同步保護,改進:Singleton& Singleton::Instance(){if (!pInstance){Lock guard(mutex); pInstance = new Singleton;}
51、return *pInstance;},問題:race condition又出現(xiàn)了,Double-Checked Locking Pattern(續(xù)二),Double-Checked Locking Pattern :Singleton& Singleton::Instance(){if (!pInstance){Lock guard(mutex); if (!pInstance){ pIns
52、tance = new Singleton;}}return *pInstance;},Table-driven pattern,代替runtime switch問題:從文件中讀入一組以CShape為基類的對象,傳統(tǒng)的做法:ReadWord(stream, &typeid);switch (typeid) {case Line_ID:pObj = (CShape *)new CLine;pObj->
53、Load(stream);break;case Poly_ID:……}pDoc.Add(pObj);,Table-driven pattern(續(xù)),維護一張表(typeid, fnCreator)根據(jù)typeid查找到創(chuàng)建函數(shù),然后創(chuàng)建對象,示例代碼如下:ReadWord(stream, &typeid);FnCreator fn = Table::Instance().Lookup(typeid);pOb
54、j = fn();pObj->Load(stream);pDoc.Add(pObj);在MFC/ATL大量用到table-driven的技術(shù)用多維表可以實現(xiàn)double-dispatch或者multi-dispatch技術(shù),用類層次代替union,Union最主要的用法Discriminated union: tag + union例如VARIANT可以用一個類層次來替代union,這對于那些不支持union的語言很
55、有意義比如Java使用類層次的好處:類型安全性代碼簡潔、清晰容易擴展反映了類型之間的本質(zhì)關(guān)系(OO)參考:《Effective Java》,舉例:用類層次代替union,,Java代碼,代替enum結(jié)構(gòu),Enum類型的缺點其中的常量沒有自己的名字空間難以擴展,使用enum來定義的類型非常脆弱多方難以合作添加常量與其他類型(比如字符串)不便于轉(zhuǎn)換typesafe enum pattern, from “Effect
56、ive Java”基本思想:定義一個類來代表單個元素,并且不提供任何公有構(gòu)造函數(shù)。相反,提供公有的靜態(tài)final域,可枚舉類型中的每一個常量都對應一個域,framework,領(lǐng)域工程單個系統(tǒng) ——〉一類系統(tǒng)有較強的抽象能力組件庫提供定制功能,允許開發(fā)人員對于框架主體部分進行修改不同層次上的framework基于二進制代碼的framework,例如MMC基于源代碼的framework,例如MFC,基于二進制的framewo
57、rk,接口:為應用中的組件提供二進制接口以對象形式封裝以功能為單位粒度大而全的接口小型接口,允許動態(tài)發(fā)現(xiàn)新的接口通信模型用戶組件與框架進行通信用戶組件之間如何通信?通過框架傳遞信息通過框架建立直通模型,基于源代碼的framework,接口:一般為抽象類,用戶提供虛函數(shù)的實現(xiàn),并注冊到主框架中用戶定制的余地比較大通信模型用戶組件與框架進行通信用戶組件之間容易建立起直通途徑,從派生類傳播類型到基類的一種模式
58、,意圖:基類有時需要根據(jù)子類的類型執(zhí)行一些功能,而基類又不可能直接得到子類的靜態(tài)類型這對于generic programming非常重要,因為編譯器要靠靜態(tài)類型來實例化模板(函數(shù)或者類)解決方案用虛函數(shù)不能解決問題 —— runtime多態(tài)性在子類中插入一個函數(shù),由該函數(shù)調(diào)用模板函數(shù)或者模板類,或者該函數(shù)調(diào)用基類中的模板成員函數(shù)僅對基于源代碼的framework適用,Framework舉例,為報社提供一套framework
59、,,,,Snap-In管理器,FrameSite,FrameSite,FrameSite,SnapIn對象,SnapIn對象,SnapIn對象,Security管理器,Database管理器,UI管理器,,,,,,,,,SnapIn倉庫,,,,IFrameSite,ISnapInfo,SnapIn DLL,SnapIn DLL,SnapIn DLL,可重用類庫的設計(一),在所有的系統(tǒng)設計中,可重用類庫的設計是難度比較大的,要做到:使
60、用:靈活性和易用性功能:廣泛性和效率經(jīng)驗非常重要實現(xiàn)同樣的功能會有許多不同的道路,如何選擇?效果怎么樣?類庫的基礎(chǔ)是否使用其他的類庫?是否使用特殊的平臺和編譯環(huán)境?參考成功的類庫起點要高,可重用類庫的設計(二),接口的設計這是類庫的關(guān)鍵,會影響到類庫的使用接口的類型:C/C++大而全的接口并不理想接口的語義一定要清晰facade模式內(nèi)存管理保證內(nèi)存分配和釋放的一致性使用要方便[out]參數(shù)的資源由誰來申請
61、?誰知道size?是否使用自定義的內(nèi)存分配器,例如針對小對象的分配器,可重用類庫的設計(三),使用各種模式模式是經(jīng)驗,成功的典范policy模式允許使用者定制類結(jié)構(gòu)型模式有助于建立起更加合理的結(jié)構(gòu)模型,而不至于層次錯綜復雜行為型模式有助于各個類之間有更好的協(xié)作模型創(chuàng)建型模式可以提供各種合理的創(chuàng)建機制模板類庫的特殊性利用模板類型實現(xiàn)compile-time的預處理熟悉編譯器的特性控制模板生成代碼,可重用類庫的設計(四)
62、,行為前置和延后在基類中提供缺省的實現(xiàn)純虛函數(shù) —— 強制子類提供實現(xiàn)利用functor或者函數(shù)指針要求(必須)子類調(diào)用父類的實現(xiàn)用宏來封裝代碼代碼風格類庫的優(yōu)化優(yōu)化需要用到內(nèi)部知識,是否暴露這些知識允許使用者用policy進行配置,用不同的實現(xiàn)配置類類似于policy的思想,在細節(jié)點上用開關(guān)進行控制,可重用類庫的設計(五),類庫的調(diào)試類庫內(nèi)部調(diào)試,使用assert支持類庫的測試比應用系統(tǒng)的測試更加嚴格類
63、庫的發(fā)行是否提供源代碼?文檔編譯設置,可重用類庫的設計(六),舉例:MFC/ATLMFC同時也具有源代碼框架的結(jié)構(gòu)傳統(tǒng)意義上的C++類庫,對Win32進行了封裝以便于使用為主要目標,優(yōu)化較少用到了許多patterns,吻合Windows應用模式涉及到許多類庫設計技術(shù)與Wizard結(jié)合產(chǎn)生基本代碼ATL用到了generic programming中許多新的技術(shù)模板技術(shù)優(yōu)化比較突出,總結(jié),C++基礎(chǔ)COM基礎(chǔ)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 積極引進先進技術(shù)
- pcb先進技術(shù)簡介
- 《先進技術(shù)》word版
- pcb先進技術(shù)簡介15641
- 水污染治理先進技術(shù)匯編
- 《水污染治理先進技術(shù)匯編》
- 生態(tài)文明建設先進技術(shù)推薦清單
- 現(xiàn)代內(nèi)燃機的先進技術(shù)
- 動力電池熱管理先進技術(shù)
- 紅外高速球先進技術(shù),夜視監(jiān)控
- 生態(tài)文明建設先進技術(shù)推薦清單
- 先進施工工藝、先進設備和先進技術(shù)的應用
- 發(fā)動機四大先進技術(shù)
- 附件《水污染治理先進技術(shù)匯編》摘錄
- 節(jié)水、治污、水生態(tài)修復先進技術(shù)匯編
- 新型水火管鍋爐先進技術(shù)研究.pdf
- 企業(yè)水電氣節(jié)能先進技術(shù)應用探討
- 引進先進技術(shù)取得了突破性進展
- 煤磨袋式除塵器的先進技術(shù)
- 2014軍事訓練器材與先進技術(shù)展覽
評論
0/150
提交評論