• 沒有找到結果。

DGV]poikn Ows h t OGPu{s mWGM09008035 G S h EQG~ C j

N/A
N/A
Protected

Academic year: 2022

Share "DGV]poikn Ows h t OGPu{s mWGM09008035 G S h EQG~ C j"

Copied!
138
0
0

加載中.... (立即查看全文)

全文

(1)

中 華 大 學 碩 士 論 文

題目:物件導向設計模式應用於發展模糊控制器軟 體類別庫之研究

系 所 別:機械與航太工程研究所 學號姓名:M09008035 黃 永 仁 指導教授: 范 志 海 博 士

中華民國 九十二年 七月

(2)
(3)
(4)
(5)

中文摘要

本論文是針對物件導向的概念,以及物件導向設計模式的運用作 一詳細的說明。並且將以模糊控制器的工作原理為例,實際設計出可 再利用的軟體類別庫。

物件導向方法的主要概念為,把真實世界視為由物件所構成,真 實世界的運作是由各個物件之間互動來產生,再將真實世界的問題對 應到分析的模型上,最後再轉換成相對應的程式碼。而物件導向設計 模式則是針對類別與物件的生成、結構、行為所集結而成的最佳設計 範本,可以解決許多在分析過程中所遭遇到的問題。

論文中將完整的分析模糊控制器的工作原理,類別庫的發展與設 計過程,以及類別庫的實際運用成果。

關鍵字:物件導向、設計模式、模糊控制器、類別庫

(6)

Abstract

The ideal of Object-Oriented and the use of the Object-Oriented Design Patterns are illustrated in detail in this research and the principle of Fuzzy-Controller for instance is chosen to design the reusable software Class-Libraries actually.

The main ideal of Object-Oriented is that the real world can be regarded as the compose of Object and the work of the real world is produced by the interactions of each Object, then lead the problem of the real world into the pattern of analysis and translate into programs finally.

In others, the Object-Oriented Design Patterns is the optimal designed method based on the assembly of Object’s creational, structural and behavioral, it can solve many problems during the process of analysis.

In this research, it analyzed the principle of Fuzzy-Controller, the development and the process of design in Class-Libraries and the result of Applying of Class-Libraries.

Keywords:Object-Oriented, Design Patterns, Fuzzy-Controller, Class-Libraries

(7)

誌謝

本論文得以順利完成,承蒙指導教授范志海博士,在這兩年來的 諄諄教悔與悉心的指導,使我在治學態度、研究方法上獲益良多,在 此致上我最誠摯的敬意與謝意。

此外,還要感謝林君明博士、黃榮興博士在論文審查時的不吝指 導並提供意見,使得本論文的架構及內容更加充實。

同時我要特別感謝鄧安村學長、劉俊宏學長、楊儒銘學長在課業 上的提點及幫助使我獲益良多,還要感謝同實驗室的同學嚴凱軍、鄒 泳富、朱清文,他們在課業與生活各方面上給予相當多的幫忙與照 顧。以及鐘資然、王清雄、李啟龍、江榮泰、葉雲鵬、鄭志平、曹世 穎、吳詩雄等同學和學弟呂文德、賴韋豪、莊凱驛、戴家郁、林家賢、

陳彥良在生活上給予相當多幫助,感謝你們的協助與幫忙使本論文得 以順利完成。

最後,感謝永遠支持我的家人以及幫助過我、愛護我的朋友,感 謝你們在精神上不斷的給我支持與鼓勵、使我能順利完成學業。

(8)

目錄

中文摘要 ……… i

英文摘要 ……… ii

誌謝 ……… iii

目錄 ……… iv

圖表目錄 ……… viii

第一章 緒論 ……… 1

1.1 研究動機與目的 ……… 1

1.2 本文架構 ……… 2

第二章 物件導向簡介 ……… 3

2.1 何謂物件導向 ……… 3

2.2 物件導向思維 ……… 4

2.3 物件導向技術的特性 ……… 6

第三章 物件導向設計模式 ……… 15

3.1 何謂設計模式 ……… 15

3.2 尋找適當的物件 ……… 18

3.3 決定物件的規模大小 ……… 19

3.4 制訂物件介面 ……… 20

(9)

3.5 制訂物件實作 ……… 22

3.6 再利用機制 ……… 27

3.7 執行時與編譯期結構之別 ……… 32

3.8 未雨綢繆 ……… 33

第四章 模糊控制器簡介 ……… 35

4.1 自動控制系統的 Fuzzy 性問題 ……… 35

4.2 Fuzzy 集合理論的問題求解 ……… 36

4.3 Fuzzy 控制工作原理初步介紹 ……… 38

第五章 模糊控制器運作流程 ……… 42

5.1 實作範例介紹 ……… 42

5.2 模糊控制器的設計 ……… 43

5.3 控制器變數的決定與變數空間的模糊分割 ……… 44

5.4 模糊控制器的控制規則 ……… 47

5.5 解模糊化 ……… 52

第六章 模糊控制器的軟體模式策略 ……… 57

6.1 歸屬函數類別 ……… 57

6.2 模糊變數類別 ……… 65

6.3 物件生成模式-Builder ……… 70

6.4 控制規則類別與控制規則庫類別 ……… 72

(10)

6.5 解模糊化類別 ……… 76

6.6 物件行為模式-Strategy ……… 78

6.7 模糊控制器類別 ……… 79

第七章 類別庫的運用與模糊控制器的軟體實作 ………… 82

7.1 程式碼的再利用-繼承 FuzzyControl 類別 …… 82

7.2 模糊控制器物件的運作 ……… 72

第八章 結論與未來展望 ……… 89

8.1 結論 ……… 89

8.2 未來展望 ……… 89

參考文獻 ……… 92

附錄 1 各類別的宣告(function.h) ……… 94

附錄 2-1 BaseFunc 類別定義(BaseFunc.cpp) ………… 102

附錄 2-2 ZType 類別定義(ZType.cpp) ……… 103

附錄 2-3 SType 類別定義(SType.cpp) ……… 105

附錄 2-4 PiType 類別定義(PiType.cpp) ……… 107

附錄 2-5 LambdaType 類別定義(LambdaType.cpp) …… 109

附錄 2-6 FuzzyValue 類別定義(FuzzyValue.cpp) …… 111

附錄 2-7 FuzzyValueBuilder 類別定義(FuzzyValueBuilder.cpp) …… 114

(11)

附錄 2-8 FuzzyRule 類別定義(FuzzyRule.cpp) ……… 116 附錄 2-9 FuzzyRuleBase 類別定義(FuzzyRuleBase.cpp)… 117 附錄 2-10 CenterAvg 類別定義(CenterAvg.cpp) ……… 118 附錄 2-11 ModMeanMax 類別定義(ModMeanMax.cpp) …… 119 附錄 2-12 Defuzzifier 類別定義(Defuzzifier.cpp) … 120 附錄 2-13 FuzzyControl 類別定義(FuzzyControl.cpp)…… 121 附錄 2-14 其它函式定義(Other.cpp) ……… 122 附錄 3 類別庫使用實例(Main.cpp) ……… 123

(12)

圖表目錄

圖 2-1 物件的封裝概念 ……… 7

圖 2-2 各類交通工具的抽象化 ……… 9

圖 2-3 繼承性 ……… 10

圖 2-4 鐘與鬧鐘的繼承關係 ……… 11

圖 2-5 覆寫(Overriding) ……… 12

圖 3-1 利用 UML 圖示法表示類別 ……… 22

圖 3-2 以 UML 表示類別可具現另一類別的示意圖 ………… 23

圖 3-3 以 UML 表示類別繼承關係示意圖 ……… 23

圖 3-4 抽象類別與具象類別的關係 ……… 24

圖 3-5 利用多重繼承機制增加新功能 ……… 25

圖 3-6 Window 類別和 Rectangle 類別的委託關係 ………… 31

圖 3-7 以 UML 表示聚合關係示意圖 ……… 32

圖 4-1 模糊控制器工作原理圖 ……… 40

圖 5-1 所要實作的受控端示意圖 ……… 42

圖 5-2 模糊控制器的基本架構 ……… 43

圖 5-3 以 5 個歸屬函數模糊分割一維變數的空間 ………… 44

圖 5-4 名稱為“小王的薪水很高”歸屬函數 ……… 45

(13)

圖 5-5 距離 s 的模糊變數 ……… 48

圖 5-6 汽車速度 v 的模糊變數 ……… 48

圖 5-7 控制器的輸出值 vout 的模糊變數 ……… 49

圖 5-8 控制規則表 ……… 52

圖 5-9 規則 7 的推論部歸屬函數 ……… 55

圖 5-10 有兩個規則真實度相同的情況 ……… 56

圖 6-1 常用的歸屬函數 ……… 57

圖 6-2 名詞命名的說明範例 ……… 61

圖 6-3 Z-Type 型的歸屬函數命名原則 ……… 62

圖 6-4 以歸屬值求明確值時的情況 ……… 63

圖 6-5 歸屬函數之間的類別繼承關係 ……… 65

圖 6-6 FuzzyValue 類別和 BaseFunc 類別間的聚合關係 …… 69

圖 6-7 物件行為模式 Strategy 結構圖 ……… 79

圖 7-1 距離 s 的模糊變數 ……… 83

圖 7-2 汽車速度 v 的模糊變數 ……… 84

圖 7-3 控制器的輸出值 vout 的模糊變數 ……… 85

圖 7-4 控制規則表 ……… 86

(14)

第一章 緒論

1.1 研究動機與目的

任何一個精良的物件導向架構中,必定充滿著許多設計模式

(Design Patterns)。一般在衡量物件導向系統的品質時,其中一種方 法就是去看看開發者是否投入足夠的心力去處理物件之間的互動關 係,在系統開發階段就注重這些機制,可產生更精簡、更易理解的架 構,遠勝許多忽視設計模式的系統。

在其它同樣需要建構複雜系統的領域裡,模式的重要性早已無庸 置疑。尤其是以著名建築師 Christopher Alexander 與其同僚,可能是 第一位提倡以模式語言( Pattern Language)來規劃建築和城鎮的人,

如今他所引發的思想已深植在物件導向軟體社群之中。簡言之,軟體 設計模式的觀念,讓開發者得以吸收其他高手的設計經驗並引為己 用。

本論文將以模糊控制(Fuzzy Control)為本,利用程式語言實作 出模糊控制器的工作原理。但並不只是設計出可以達到目的的程式而 已,設計的過程中,我們將導入物件導向程式設計的方式,並且進一 步的規劃出可再利用的程式碼。為達到所謂“可再利用的物件導向軟 體”,本論文也將討論如何利用設計模式,來發展出更富彈性、更模

(15)

組化、更具再利用性、更易為人理解的類別庫(Class Libraries)。

1.2 本文架構

本論文由於必須詳細的介紹類別庫的發展過程,故第二章將簡單 的介紹物件導向觀念,而第三章將說明何謂設計模式以及設計模式如 何解決問題;第四章則為模糊控制的背景介紹;第五章則說明模糊控 制器的運作流程;第六章為類別庫的完整發展過程,在第六章中,也 將有兩個設計模式-物件生成模式 Builder 和物件行為模式 Strategy 的說明以及實際運用;第七章則以第六章中所發展出來的類別庫,實 際的運用在案例上;第八章則是結論與未來展望。

(16)

第二章 物件導向簡介

2.1 何謂物件導向(Object-Oriented)

物件(object)這個名稱大約是出現於 1967 年,它的英文原意是 表示“各式各樣的事物”,但是當時並沒有統一的稱呼,有人叫它實 體、項目、物體、個體等,但現在大多人通稱它為“物件”。

物件導向(object oriented)的觀念源於 1967 年瑞典,由挪威學 者奧里(Ole-Jone Dahl)設計的模擬語言 Simula-67,該語言首先提 出物件(object)、封裝(encapsulation)、資料抽象化(data abstract)

及繼承( inheritance)的概念。Simula-67 主要用於模擬;Simula 的物 件具有“自身獨立存在”並能在模擬過程中以一定的含義彼此溝通 信息。它是目前許多的支援物件導向語言之根基,例如:Smalltalk、

C++。

當要開始分析及設計系統時,首要工作就是決定系統是由那些物 件所組成。物件是物件導向的基本思維單位,物件具有其特有的屬性

(attribute)及行為(behavior)。它可以是一個抽象物、觀念、概念、

或是一個有明確界定範圍的事物,重點是要在我們要解決的問題中是 具有意義的。例如:我們要設計一個選課資訊系統,則可能的物件包 括學生、課程、教師與選課等物件。利用物件的觀念,再關聯“封裝”

(17)

(encapsulation)、“繼承”(inheritance)、及“多型”(polymorphism)

(或稱“同名異型”)來架構出一個系統。把資料與動作都封裝在物 件之中,使每個物件都可以獨立的和其它物件交換資料和互相溝通,

物件也可經由其它物件的觸動而產生反應,以達成一項既定的目標。

使用物件所擁有之概念原則,使建立出來的系統更加的完整與穩定,

以及可重複利用等優點。

例如說:學生和老師都是物件,老師問學生問題是一個觸動事 件,學生回答老師的問題則是反應。系統所可能發生的行為及相關資 料的轉移,若是透過一連串物件間的互動與物件狀態的改變,便更易 於被了解。也因此使用物件的觀念使我們相當的容易去定義、開發和 維護系統。

2.2 物件導向思維(Object-Oriented thinking)

物件導向思維模式是系統分析人員對問題( problem)的看法,以 及如何藉由對問題領域的了解而導出解決方法的思維模式。透過這種 思維模式,希望藉由物件的行為及資料的轉換達到描述系統功能需求 的目的,並以此建立系統。物件導向的思維模式,首先在於了解問題 及找出物件和物件的結構、運作及相互之間的關係。最後再思考及進 行電腦化設計的工作。如 Grady Booch 所說:「物件觀念會普及的原 因是它能協助人們去克服各式各樣系統中的根本複雜性」。[1]

(18)

組成物件導向的思維模式包括了下列三個重要觀念:

1. 實體對應(entity mapping)

物件的實體對應是一種從下到上(buttom-up)的思考模式。由問 題領域去發掘關鍵性的組件。如圖書處理系統中的讀者、書籍。

再由這些組件可能的延伸功能,如借書、續借等,持續將問題具 體化。物件的實體對應,將使問題領域的描述不會悖離事實,也 較不違反程序式思維「上到下」方式,造成整合上的困難。

2. 抽象化(abstraction)

抽象化就是一種分類的概念,將物件中具有相似屬性及行為的物 件歸類成一個類別。抽象化的效益是可以簡化問題領域的複雜 度。例如:世界上有白人、黑人、黃種人、可以利用抽象化的概 念抽象為“人”。

3. 擬人化

物件導向思維中將所有問題領域中的物件都加以擬人化,物件不 但擁有其屬性及行為,且物件與物件可以相互的溝通及互動。就 如同人一般,每個物件都是唯一的,即使它們所具有的屬性值都 相同,兩個物件之間是有區別的。例如:書本類別的屬性有名稱、

種類、價格等,運作有借書、還書等。

(19)

物件導向思維所帶來的效益有兩項:

1. 符合人性思維模式

因為人類具有極佳的抽象化能力,能以抽象的表示法,來理解與 解釋原本複雜的系統架構。物件導向技術的思維方式就是要人們 發揮抽象化的想像的能力,藉由建立抽象的模式以便認識及簡化 複雜的系統。

2. 易於剖析問題

物件導向思維可以幫助系統分析師了解問題與軟體解決方案

(solution)之間的對應關係,讓問題領域專家(domain export)

和使用者對於系統架構以及開發程序有一定的了解,並且可以讓 使用者有興趣參與系統的開發工作。

2.3 物件導向技術的特性

物件導向主要是由四個基礎概念所構成,分別為封裝性

(encapsulation)、抽象化(abstraction)、繼承性(inheritance)、以及 多型(polymorphism)這四個觀念。同時這四個觀念亦可說是物件導 向技術與傳統軟體開發技術最大的分野。四個特性分述如下。

所謂的封裝性就是將物件實例的屬性與方法一起封裝到類別 中。這是一種資訊隱藏(information hiding)的概念。如下頁圖 2-1 所示:

(20)

屬性

封裝

運作或方法

圖 2-1 物件的封裝概念

那麼,什麼是資訊隱藏呢? 在傳統的程序導向程式設計中,資料 結構與函數是分離的,這樣當我們在維護程式時就會產生很大的困 擾;而在物件導向中便將這兩個東西緊密的包圍在一起,使得一物件 內的資料只有透過適當的介面(方法)才能予以修改,這便是資訊隱 藏。

透過這個資訊隱藏的方式,將物件的內外部分開來,其它物件只 能藉由外部的介面取得其提供的資料,物件內部的細節資料則隱藏起 來,其它物件即無法瞭解此物件的內部細節,若不經過允許之窗口(即 此物件提供之方法),便無從更動此物件內的資料。

檔案 檔案名稱 檔案型態 檔案大小 檔案日期 Open( ) Read( ) Write( ) Close( ) Print( )

(21)

封裝內部對程式設計者提供了兩項主要的好處:

1. 實現方式的隱藏(implementation hiding)

實現方式的隱藏是指對某一物件其內部實現方式的保護。一個物 件由以下兩個部份所構成:1.公用介面, 2.由內部資料和方法所組 成的私有區域。內部的資料和方法是一物件中不能從物件的外部 來存取的地方。這樣子的設計其主要優點為,這些私有區段就算 自行改變也不會影響到使用該物件的程式。

2. 模組性(modularity)

模組性意指一個物件的維護和其它的物件無關。因為一個物件其 內部區段原始程式碼維護是和其介面分開,所以你可以咨意地改 變內部區段的內容而不用擔心你所做的改變會產生問題或影響其 它模組的功能運作。因為封裝將物件內外部分開,所以在系統移 植、異動或修改時,便不會有牽一髮而動全身的漣漪效應,同時 也增加了系統在維護上的便利。

抽象化是指將焦點放置於物件的整體而非細節,重點在於表現什 麼是物件? 物件做什麼? 而忽略其它與目的無關的細節。像我們在將 外界實物對映到電腦系統中時,常忽略一些問題的細節部份,如此,

不但可以將我們對整個問題的思考仍維持在一定的概括性之上,亦可 讓我們不致陷於旁枝末節的泥沼中。

(22)

藉由抽象化讓我們剔除物件間的差異,使我們只看到共同處,如 此我們可以降低對問題的複雜度,同時可將系統內的物件分類成不同 的類別。

例如:在真實世界中,我們可以把摩托車當作是一個物件,也可 以把腳踏車、汽車、卡車等當作是一個物件,若我們沒有從抽象化的 角度來看待這些物件時,則會發現,這個世界將充滿無數的類似物 件,使我們會不知如何去了解它們。但若透過抽象化觀念來剔除物件 間的差異,則我們可以將這些物件抽象化為“交通工具”這個類別,

如圖 2-2 所示,透過此類別,我們可以降低對問題的複雜度,即了解 到這些物件只是一種代步的工具而已,如此,可以使我們對問題的思 考,維持在一個概括性之上。

交通工具

圖 2-2 各類交通工具的抽象化

………

摩托車 腳踏車

輪船 飛機

卡車 汽車

(23)

當我們將各物件抽象化為“交通工具”類別後,我們可再依據物 件導向的另一特性“繼承性”,將交通工具再細分為陸上交通工具、

水上交通工具、空中交通工具等三個類別,如圖 2-3 所示。

圖 2-3 繼承性

談到繼承,就不可不說到“軟體再用”(software reuse)的觀念。

每個人都知道,在蓋房子時,都是先從打地基開始建造,但是若在系 統發展時,亦用這種平地起高樓的想法來開發時,那整個軟體業界的 生產力又怎麼能大幅的提高呢? 因此,為了有效提升軟體開發的生產 力,便有人提出了軟體再用的概念,而這個想法也被應用在物件導向 技術。

對於物件導向技術而言,經由封裝而成的類別就是一個最佳的可 重覆使用軟體元件。而“繼承性”便是用來避免相關資訊重覆出現的 一個觀念。

繼承(inheritance)又稱為一般化(generalization)與特殊化

(specialization)的關係,例如 A 繼承 B,乃指物件類別 A 是物件類

交通工具

陸上交通工具 水上交通工具 空中交通工具

(24)

別 B 的一種,因此物件類別 A 可以繼承物件類別 B 的屬性與方法。

例如汽油車和電動車可看成是繼承自車子類別的子類別。這兩種新的 車子類別都有共同的“車子”的特質,但它們也有僅屬於它們的自己 的一些特質。汽油車有一個油箱和汽油蓋,而電動車有個電池和充電 的插頭。

另外,兩個以上類別一般化後之類別稱為基礎類別(base class),

也可以稱為父類別。子類別與父類別的階層關係是類別階層(class hierarchy)的一種。每一類別會定義所屬之屬性與方法,當此類別被 要求提供某種服務而需執行某方法時,若此類別本身定義有此方法,

則可以直接執行此方法,否則此類別會沿著類別階層由下往上找,直 至找到為止。

圖 2-4 鐘與鬧鐘的繼承關係

如上圖 2-4 所示,鐘是鬧鐘的父類別,而鬧鐘是鐘的子類別。當

顯示目前時間 儲存時間 設定時間

鬧鐘

顯示起床時間 設定起床時間 響鈴

目前時間

起床時間

(25)

因此鬧鐘會沿著類別階層由下往上找,往上找到鐘這個類別後,便看 看他是否有提供顯示目前時間的運作,若有則執行它;反之,則繼續 往上找,直到找到為止。但在不同階層的類別中,同樣名稱的方法可 能有不同定義,執行方法時,會沿著類別階層由下往上找,因此,子 類別的定義將優先於父類別的定義。這種子類別的方法使父類別的方 法相對失效的情況,稱為覆寫(overriding)。

如圖 2-5 所示,當我們要計算球員薪資時,由於見習球員、正式 球員和臨時球員的薪資計算方式皆不相同,故雖然每個類別都有計算 薪資這個運作,但每個運作的內部計算方法是不相同的。因此,若要 得知見習球員的薪資是多少時,則會執行見習球員這個子類別的計算 薪資運作,而不會執行球員這個父類別中的計算薪資運作。

圖 2-5 覆寫(Overriding)

球員

計算薪資

臨時球員

計算薪資

見習球員

計算薪資

正式球員

計算薪資 累計薪資

單埸薪資 安打紅利

月薪 年薪

(26)

由上可知,繼承性是類別之間的一種再分類關係,它會讓幾個類 別之間具有相同的資料結構或運作程序,減少重覆的程式碼,以達到 物件重覆使用的目的。

多型的觀念基本上與繫結(binding)有不小的關係。繫結可分為 靜態繫結(static binding)與動態繫結(dynamic binding)兩種。

所謂的靜態繫結是指程式在執行時所需引用的一些變數、函式等 相關資訊,在原始碼編譯時期時便已決定其記憶體位址大小等。而動 態繫結則是指在程式執行時期,系統才將訊息和方法連結在一起,而 不是在編譯的時候。訊息是送到物件的介面,用來啟動物件的工具,

而方法則是在訊息送達物件介面後,被選取的運作程序。例如,媽媽 叫兒子去買早點,媽媽物件只需把“買早點”的訊息送給兒子這個物 件,而不需要知道兒子物件是如何應用方法來完成“買早點”的動 作。若是兒子有好幾個,動態繫結會自動地把訊息送給適合的物件方 法執行,無須擔心是哪個兒子物件完成的。因此,透過動態連結的功 能,我們不用事先考慮使用物件的型別,只要把訊息送出即可。等到 程式執行中,看哪個物件應該配合這個訊息,再把訊息和這個物件的 方法繫結,然後執行這個方法。一般說來動態繫結提供了較大的程式 設計彈性,但相對的,在執行速度上可能就不及靜態繫結所編譯過的 程式。

(27)

在物件導向技術中,利用了動態繫結的方式,將相同名稱的方法

(成員函式)在程式執行的時候才視所要處理的物件決定實際呼叫的 函式。對於這種用同樣的表示方法而能處理不同類別物件資料的方 式,就稱之為多型。

利用多型的觀念,讓我們可以重複使用已經發展完成的運作元件

(code re-usability)。同時讓我們可以建立通用的軟體元件(generic software components),或使用已經存在的程式碼,來建立新的類別,

充分增進了軟體發展的彈性(flexibility)。

最後,我們可以整理出物件導向分析與設計的工作,主要是分成 以下四個步驟:

1. 界定問題領域之類別:找出系統相關的類別(class)。例如在線上 訂書系統中,有客戶、書、交易、訂書單等類別。

2. 詳細定義類別:定義類別(class)的屬性(attribute)、行為(behavior)

與方法(method)。例如:廚師類別有姓名、年齡、性別等屬性,

炒菜、作飯等行為,以及作各項佳餚的方法,如宮保雞丁的煮法。

3. 界定類別之間的關聯:定義出這些物件和類別之間的關係

(relationship),並建立類別的階層圖。

4. 實作:實作出物件及類別。

(28)

第三章 物件導向設計模式

3.1 何謂設計模式

設計物件導向軟體很難,設計可再利用(reusable)的物件導向 軟體更難。你必須找出適切的物件,分解成大小合宜的類別,定義類 別介面和繼承階層,並建立彼此之間的關聯。設計的過程中既要針對 眼前的問題領域,又得一般化到足以面對未知情境;還希望日後不必 再重新設計一次,或者至少不必大改特改。想一開始就弄出可再利 用、彈性夠大的“正確”設計是不可能的,縱然可能,也很困難;想 達到再利用的目標,就免不了一改再改。但有經驗者終究還是做出令 人讚嘆不已的設計,一般人卻被一大堆可能性嚇著了,動輒退縮回較 熟悉的傳統非物件導向技術。其實這也是經驗之間的不同。

究竟是哪裡不同呢? 專家會避免從零開始構思解決方案,他們會 引用過去的經驗。他們一發現有好的解決方案,就會一再使用,這就 是專家之所以稱之為專家的主要原因。有時我們會發現,許多物件導 向系統裡面都有一再出現的類別互動模式,這些模式不僅解決了特定 問題,同時也讓物件導向系統更富彈性、更優雅、更具再利用性質,

讓設計師藉由過去的成功經驗引領出新的設計。熟悉這些模式的設計 師,不必再苦思解決方案,馬上就能把模式套用上去。

(29)

舉例來說,小說家和劇作家很少會憑空想像故事角色,他們會遵 循一些像是“悲劇英雄”(如哈姆雷特等)或者“浪漫故事”之類的 模式。同樣的,物件導向設計師也會遵循一些模式,像是“將狀態表 達成物件”、“點綴物件,以增刪某些特性”。只要懂得模式,許多 設計點子自然接踵而至。

設計模式讓成功的設計與架構更容易再被利用,將成功的技術整 理成設計模式,可讓新系統開發者更快進入狀況。設計模式讓你有機 會挑選最具再利用潛力的設計方案,在釐清類別規格、物件互動關 係、背後用意的過程中,更可改善文件品質及維護成本。簡言之,設 計模式讓設計師更快設計出“正確”東西。

著名的建築師 Christopher Alexander 說:「每一個模式都是在描述 某種一再出現的問題,並描述解決方案的核心,讓你能據以變化出各 種招式,解決上萬個類似的問題。」[2]雖然他是針對建築物和城市 而說,但也適用於物件導向設計模式。雖然在這裡所討論都是環繞在 物件和介面上,而不是建築物的牆和門;不過骨子裡,兩種模式都是 針對特定脈絡中特定問題的解決方案(a solution to a problem in a context)。

一般來說,模式有四個主要成份:

1. 模式名字:對問題、解決方案、產生效果所訂的簡短代號。模式

(30)

名字可擴增我們的設計語彙,讓我們以更高的抽象化層次設計系 統,讓我們用這些詞彙和同事交談、寫作、反思,讓我們更容易 獨自思考或與人溝通種種設計取捨。

2. 問題:模式的應用時機,描述待解問題及情境。它可能是特定的 設計問題,像是如何將演算法包成物件,也可能是某種欠缺彈性 的結構性症狀。有時候也會描述一些使用模式的先決條件。

3. 解決方案:解決方案的組成物、彼此間的關係、各自的職責、協 同合作方式。此處並不述明最終的實作細節,因為模式就像是一 個樣板模子,可套用到多種不同的情況;模式旨在提供一種抽象 性描述,告訴我們該如何將各組成份子(此處指的是類別和物件)

以一種一般性的配置法則來解決某種問題。

4. 效果:模式的施行結果,以及實務上的權衡取捨事宜。雖然在描 述設計細節時並不常提到這個,但在評估替代方案、評估成本及 效益時卻是非常重要的。我們通常會考慮到時間和空間的取捨,

也可能考慮到程式語言和實作細節。因為再利用性是物件導向設 計的要件之一,所以這裡也會探討模式對系統彈性、延伸性、可 攜性的影響。把這些事項講清楚,有助於了解與評估。

人的觀點會影響他對“什麼算是模式,什麼不算”的認定,例如 說:張三的模式可能只是李四眼中微不足道的小玩意。在本論文中使

(31)

用的模式,將著眼於抽象化層次較高的模式。另外,設計模式也不是 在談鏈結串列或雜湊表(皆為資料結構中的名詞)的設計,雖然這些 也都可弄成類別,也都有可再利用的性質,但也不是在談更複雜、與 特定應用領域密切相關的應用軟體和子系統;在本論文中所使用到設 計模式是由彼此互動的物件類別所組成,稍加調整即可解決某特定情 境當中的一般性設計問題。

設計模式能解決許多物件導向設計者每天碰到的問題,而且解法 不只一種。以下就簡單的介紹。

3.2 尋找適當的物件

物件導向程式是由物件所構成。物件將資料和可施於其上的程序 包裝在一起,此處的程序通常叫做 method 或操作(operation)。當物 件收到客戶端(client)送來的要求(request)或稱為訊息( message)

時,就會執行對應的操作。

訊息是唯一可令執行操作的管道,操作則是唯一可改變物件內部 狀態的管道。有了這些限制,物件內部狀態可說是被妥為封裝了起來

(encapsulation):無法接觸及無法自外界窺視。

物件導向設計最難的地方就是將系統分解成一個個物件。其中有 許多因素:封裝、規模、相依性、彈性、效率、演進、再利用性……

都會影響到分解決策,更糟的是:不同變因還會互相衝突,讓事情更

(32)

加困難。

各家各派物件導向設計方法論都有各自偏好的應對措施。有的是 教導先陳述問題,挑出名詞和動詞,再據以造出對應的類別和操作;

有的則是教導專注於系統的互動和責任歸屬;有的則是教導塑模真實 世界,再將分析階段尋得的物件轉換成設計。

設計階段的物件有許多是來自分析階段,但前者的產出,多半是 真實世界所沒有的類別,或低階如陣列,或高階如 Composite 模式[3]

(Composite 會以真實世界所沒有的一致性抽象觀點看待物件)。嚴守

“塑模真實世界”的原則反而會讓系統綁死在現在,無法因應未來變 化;在設計階段所引進的抽象化考量,是讓系統更富彈性的關鍵。

設計模式幫助我們辨識出較不明顯的抽象化對象以及可捕捉這 些對象的物件。例如說,雖然在真實世界並沒有代表流程或演算法的 物件,但這些物件卻是彈性設計的關鍵。Strategy 模式[4]描述如何實 作出一整族可相互替換的演算法,State 模式[5]將個體的每一個狀態 表示成物件,這兩種物件都很難在分析階段或早期設計階段看到,但 它們卻能讓設計能夠更富彈性及再利用性。

3.3 決定物件的規模大小

不同的物件,大小和數量的差別相當大,可能小到如零件、大到

(33)

決此一問題。Facade 模式[6]描述如何將一整個子系統弄成物件,

Flyweight 模式[7]則描述如何承載一大堆小規模的物件。有些設計模 式教導如何將物件分解成較小的物件集,Abstract Factory 模式[8]和 Builder 模式[9]做出的物件專門負責打造其它物件,Visitor 模式[10]

和 Command 模式[11]做出的物件專門負責替另外一個或一群物件處 理訊息。

3.4 制訂物件介面

物件所宣告的每一個操作,都得訂出該操作的名字、參數、傳回 值,也就是該操作的外貌簽名(signature)。所有已訂定的物件操作 之外貌名,稱為此物件的介面( interface)。物件的介面,界定出能送 給此物件的訊息類型;只有符合物件介面的外貌簽名,才能送給此物 件。

註:所謂的外貌簽名(signature),其實指的就是函式原型(function

prototype),而描述操作外貌簽名的操作名字、參數、傳回值,指的就

是函式的名稱、參數列、以及函式的回傳值型別。

我們用型別(type)來指稱某一特定的介面,像物件“具有 window 型別”的意思是“它能接收 window 介面所定義的所有操作訊息”。

一個物件可能具有許多型別,不同物件也可能具有同一型別。物件的 某一部份介面可用某一個型別來指稱,另一部份介面可用另一型別指 稱。同一型別的兩個物件不必從頭到尾都相同,只要“介面”所管轄

(34)

的部份相同即可。介面也可包含其它介面:當型別 A 是型別 B 的子 型別(subtype)時,A 的介面會包含 A 的父型別(supertype)B 所具 備的介面;通常會說子型別 A 繼承了(inherit)父型別 B 的介面。

介面是物件導向的基石。想辨識物件,只有靠介面這條路;若不 知道介面,便無從得知物件的資訊,也無法叫它做任何事。物件介面 並不含任何實作事項,物件有權自由決定該如何實作這些操作,因 此,兩物件即使介面完全一樣,也可能會有完全不同的實作。

註:這樣的介面之下所包含的外貌簽名,皆稱為虛擬函式(virtual function)

當物件收到訊息要求時,會同時根據訊息和物件來決定該啟動哪 一個操作。實作方式不一樣的兩物件可能都會支援同一訊息要求,所 以在執行期決定該將此一要求導引到哪個物件的哪個操作的機制,就 叫做動態繫結( dynamic binding)。動態繫結意謂著:所送出的訊息,

直到執行期才會知道送到哪一個實作體上,如此一來,就能針對特定 介面來寫程式,讓符合特定介面的物件來接收訊息。動態繫結能夠在 執行期以同一介面的多個物件交互替換,這種替換性質就叫做多型

(polymorphism),是物件導向系統的重要觀念。有了多型,客戶端 就不必對引用物件做過多假設,只須支援特定介面;亦可簡化客戶端 的定義、拆解物件、在執行期改變彼此關係。

設計模式也制定介面之間的關係,尤其是會要求某些類別必須具

(35)

有類似的介面,或者限制某些類別所該具備的介面。例如說,Decorator 模式[12]和 Proxy 模式[13]都要求 Decorator 和 Proxy 物件必須和它們 的對象有相同的介面。Visitor 則要求它的介面必須能反映所有對象的 類別。

3.5 制訂物件實作

物件的具體實作細節是由類別所定義,類別定義出物件的內部資 料和佈局、物件所能執行的操作。

UML(United Modeling Language,統一塑模語言)將類別畫成 長方形,最上面是類別名字,其下列出類別所定的資料,最下面列出 類別的操作;三者之間以橫線隔開。傳回值和個體變數(instance variable)的型別可寫可不寫,因為並未假定所用的是靜態型別程式 語言。(如圖 3-1)

圖 3-1 利用 UML 圖示法表示類別

類別可具現出(instantiate)物件,我們可稱此物件是類別所生之 個體(instance)。具現程序會替物件內部資料(由個體變數組成)及

ClassName

InstanceVariable1

InstanceVariable2:Type

……

Operation1( )

Operation2( ):Type

……

(36)

搭配的操作配置出記憶體空間,同一類別可具現出許多相似的物件個 體。

以 UML 表示類別可具現出另一個類別的物件,箭頭指向被生成 者。(如圖 3-2)

<< create >>

圖 3-2 以 UML 表示類別可具現另一類別的示意圖

我們可利用類別繼承機制(class inheritance)從既存類別定義出 新類別。當子類別(subclass)繼承親代類別、父類別(parent class)

時,前者會包含後者所有的資料和操作定義,子類別的物件個體會包 含這個子類別和親代類別所有的資料、能夠執行這個子類別和親代類 別所有的操作。UML 以空心三角形箭頭表示繼承關係:(如圖 3-3)

圖 3-3 以 UML 表示類別繼承關係示意圖

抽象類別(abstract class)主要目的是替多個子類別訂出共通介 Instantiator Instantiatee

ParentClass

Operation( )

SubClass

(37)

面。抽象類別會將部份或全部的實作細節交付給子類別的操作去實 現,因此抽象類別無法具現出物件個體。抽象類別有宣告、但未實作 的操作,叫做抽象操作(abstract operation);與抽象類別相反的則叫 做具象類別(concrete class)。

子類別可對承襲親代類別的行為加以修改或重新定義,更精確地 講:子類別可覆寫(override)親代類別所賦予的操作。覆寫功能讓 子類別有機會以異於親代類別的方式處理訊息要求。類別繼承能藉由 延伸既存類別以定義出新類別,讓你更容易定義一整族功能相近的物 件。

為便於和具象類別相區隔,UML 的類別圖將抽象類別名字和抽 象操作名字寫成斜體,也可添加一段虛擬碼在操作身上。(如圖 3-4)

implementation

pseudocode

圖 3-4 抽象類別與具象類別的關係

Mixin 類別專門用來替其它類別增添額外的介面或功能。它和抽

AbstractClass

Operation( )

ConcreteSubclass

Operation( )

(38)

象類別很像,都不是用來具現物件實體的。Mixin 類別需要動用多重 繼承機制:(如圖 3-5)

圖 3-5 利用多重繼承機制增加新功能

物件的類別(class)和型別(type)之間的分別有些差異。物件 的類別乃定義物件的實作方式:定義物件的內部狀態及操作的實作 碼。相對的,物件的型別只定義它的介面:物件可回應哪些訊息要求。

一個物件可以有許多型別,不同類別的物件也可以具有相同的型別。

當然,類別和型別有很密切的關係。類別因為有定義出可執行的物件 操作,自然也定義出物件的型別;當我們說“某物件是某類別的具現 個體”時,自然也意謂著“此物件具有支援此類別所制定的介面”。

我們也必須留意分辨類別繼承和介面繼承之間的差異。類別繼承 ExistingClass

ExistingOperation( )

Mixin

MixinOperation( )

AugmentedClass

ExistingOperation( ) MixinOperation( )

(39)

佈局的機制;相對的,介面繼承則在描述物件之間的可替換性。

這兩種觀念很容易弄混,因為許多程式程言根本就沒有區分。像 在 C++語言裡,“繼承”同時代表“介面繼承”和“實作繼承”兩種 意思。所以 C++程式中,介面繼承的標準寫法是“public 繼承某一具 有(純)虛擬函數的類別”,至於最純粹的介面繼承,就只能勉強以

“public 繼承某一純抽象類別”的方式來近似;最純粹的實作繼承或 介面繼承,就只能勉強以“private 繼承”的方式來近似。

基本上,類別繼承這種機制只是以“再利用親代類別功能”方式 來延伸應用程式的功能,可根據既有類別快速定義出新品種的物件,

承襲既有類別的特性,花最少的力氣得到所想要的結果。但“再利用 實作碼”功能並不是繼承的全部;定義一整族具備同一介面的物件

(通常是以“繼承某一抽象類別”方式實作)也是相當重要的。因為 多型需要它。

若繼承用得夠謹慎(有人認為這才真的算是用得正確),所有自 抽象類別衍生出來的類別都會共用前者的界面,這意謂著:子類別只 會添加或覆寫,並不會隱匿親代類別的操作,如此一來,所有子類別 都能回應此抽象類別的介面訊息要求,都成為抽象類別的子型別。

堅持只以抽象類別介面的角度來操控物件,有兩個優點:

1. 客戶端不必知曉所用物件之確切型別,只須知道這物件的確符合

(40)

它所預期的介面即可。

2. 客戶端不必知曉所用物件之確切類別,只須知道這介面是由哪一 個抽象類別所定義的。

如此即可大幅降低子系統之間的實作依存關係,反映出底下這項 可再利用物件導向設計的原則:

針 對 介 面 而 寫 , 不 要 針 對 實 作 。

Program to an interface, not an implementation.

宣告變數時,不應該宣告成是某特定具象類別的物件個體,應該只宣 告成某抽象類別所定義的介面,這才是設計模式的主軸。

當然,最後終究還是得在程式的某處具現出具象類別的物件實體

(亦即:指定特定的實作細節),此時生成模式(Abstract Factory、

Builder、Factory Method、Prototype、Singleton)就能派上用場。這些 模式抽象化物件的生成過程,給我們好幾種將介面與實作連繫起來的 具現方式。生成模式可確保系統乃是針對介面而寫,而不是實作。

3.6 再利用機制

大多數人都能了解物件、介面、類別、繼承之類的觀念,但真正 用它們打造出具彈性及再利用性的軟體才是一大挑戰。

在物件導向系統裡最常見的兩種再利用技術是類別繼承與物件

(41)

另一物件的實作細節,這種以子類別促成的再利用方式,通常稱為白 箱式再利用( white-box reuse),“白箱”指的是能見度:在繼承機制 下,子類別常可透視親代類別的內部。

另一種方式是物件複合:將既有物件組合、複合起來,以拼出更 複雜的功能。被選來組裝的物件,必須有明確定義的介面。這種再利 用方式稱為黑箱式再利用(black-box reuse):各物件內部細節全都隱 匿不可見,形同“黑箱”。

繼承和複合都各有優缺點。類別繼承是在編譯期就靜態定義好 了,有程式語言的直接支援,容易使用,也容易逆向修改再利用之物 件的實作細節:子類別只要覆寫某些親代操作,即可影響原物件的行 為。

但類別繼承也有缺點。第一、無法在執行期才變更承襲自親代類 別的實作細節,因為繼承是在編譯時期就定義好的。第二、更糟的是,

親代類別通常只定義子類別所需之實體佈局當中的一部份而已,但繼 承會將親代類別的內部細節曝露給子類別看到,所以許多人常批評說

“繼承會破壞封裝性質”。子類別和親代的實作細節會過份相依,使 得親代實作細節一有變動就會波及子類別。過於依存實作細節,會有 害子類別的再利用潛力。萬一繼承下來的實作方式並不適於新的問題 領域,就得改寫親代類別,或者換成另一個更合適的;這會限制住彈

(42)

性和再利用性。解決方法是:只繼承抽象類別,因為通常抽象類別幾 乎不含實作部份。

物件複合的做法則是:在執行期動態地指涉其它物件,這需要遵 從彼此的介面,也因此介面必須訂得更為妥當,在拼裝時才不會有格 格不入的問題。雖麻煩,但值得:物件只能透過介面來存取,便能確 保封裝性質;只要兩物件屬於同一型別,便能在執行期交互替換使 用;尤有甚者,我們是遵照物件的介面來實作它,所以實作碼之間的 相依性會大幅降低。對系統設計而言,物件複合尚有另一個作用:它 封裝得比類別繼承更好、更針對單一任務;類別和類別階層仍舊輕薄 短小,不易長成難以駕馭的怪獸。然而,物件複合的設計成品卻會產 生較多的物件(倘若產生的類別較少),系統行為便不再只取決於單 一類別身上,而是依各物件之間的交互作用而定。

因此,第二項物件導向設計原則即是:

多 用 物 件 複 合 技 術 , 少 用 類 別 繼 承 。 Favor object composition over class inheritance.

理想情況下,不必為了再利用的目的去打造新的元件,應該只要 以物件複合方式將既有元件拼裝起來就能弄出想要的功能;可惜現實 並不完美,既有元件不太可能夠用,此時就需要繼承機制來再利用既

(43)

而,根據許多經驗,設計師往往過於濫用繼承機制,而且較具再利用

(也較為單純)的設計往往較傾向物件複合機制。而事實上物件複合 技術也一再出現在設計模式裡。

委託(delegation)技術讓複合技術和繼承一樣強大有力。在此 技術下,有兩個物件協同處理訊息要求:訊息接收者物件會將訊息操 作委託給被委託者(delegate;代表)去全權處理。乍看之下似乎帶 了點“子類別將訊息要求推給親代類別去處理”的味道,但是以繼承 而言,被繼承的操作仍可隨時觸及原來的接收者物件;如果想讓委託 技術也享有此一特性,接收者就得把“自己”也丟給被委託者,好讓 被委託的操作能觸及原來的訊息接收者。

舉例來說,即使我們不把 Window 弄成 Rectangle 的子類別(視 窗幾乎都是長方形),仍可襲用 Rectangle 的行為:設置一個 Rectangle 個體變數,將相關的事務轉交、委託給它去處理;換句話說,Window 並不是一種 Rectangle,而是含有一個 Rectangle。不過現在 Window 必須手動將相關的訊息要求轉交給內含的 Rectangle 個體去處理,不 能像以前繼承時代那樣自動交接。

在下頁圖 3-6 中,Window 類別將 Area( )操作委託給內含的 Rectangle 個體去處理,其中實線箭頭代表說:此類別含有一個 reference(在 C++中,就是指標),指涉到另一個類別的物件個體。

(44)

Reference 還可附上可有可無的名字,如此例的“rectangle”。

1 <<delegate>> 1 rectangle

return rectangle->Area( ) return width * height

圖 3-6 Window 類別和 Rectangle 類別的委託關係

委託的主要優點是:更容易在執行期拼裝及改變行為,例如說,

如果想把視窗換成圓形,只要把 Rectangle 個體換成 Circle 即可(假 定 Rectangle 和 Circle 是屬於同一型別)。然而委託技術也和其它基於 物件複合的再利用技術一樣有著相同的缺點:動態、高度參數化的軟 體,比靜態的軟體更難理解,執行得也更慢,不過人腦效能終究還是 比機器效能更重要。委託最好是用在能簡化問題的埸合,而非更複雜 化。不過很難明確說明委託技術的運用時機,這得取決於情境及經 驗;最佳運用時機就是有紀律地使用,也就是說,用在典型的設計模 式裡。

Window

Area( )

Rectangle

width height Area( )

(45)

3.7 執行期與編譯期結構之別

一般來說,物件導向程式的執行期結構和程式碼結構並不怎麼相 像。程式碼結構(即類別繼承體系)在編譯期就定死了,程式的執行 期結構則是變動迅速的物件通訊網。事實上,兩者大部份是相互獨立 的,想由其中一者認識另一者,猶如想以動植物這種靜態分類體系來 理解整個生態系的動態層面一樣可笑;反之亦然。

在此分辨一下物件聚合(aggregation)與熟識(acquaintance)關 係的異同,以及它們在編譯期與執行期的角色差異。聚合關係是指:

物件 A 持有或擔負另一物件 B,通常會說物件 A 擁有(have)另一 物件 B,或說物件 B 是另一物件 A 的一部份(part of)。聚合關係也 意味著:被聚合者 B 和它的擁有者 A 的生命期完全一樣。

熟識關係是指:物件 A 只知悉(know of)另一物件 B,有時也 稱為連繫關係(association)或使用關係(using)。物件可引用對方的 操作,但並不擔負彼此之責,可說是比聚合關係更薄弱、物件耦合性 更低。

在 UML 裡,連繫關係是以實線表示,附帶可有可無的方向性箭 頭;聚合關係則是再將空心菱形添加在聚合母體端:(如圖 3-7)

AggregateInstance

圖 3-7 以 UML 表示聚合關係示意圖

Aggregator Aggregatee

(46)

聚合和連繫關係的實作方式常常是一樣的,容易弄混。在 C++裡,聚 合關係可用成員變數(member variable)直接實作成真正的物件實 體,但更常寫成指標或 reference 去指向物件個體;連繫關係亦然。

因此,連繫關係和聚合關係終究還是得視目的而定,無法只靠程 式語言。所以在編譯期結構中很難看出兩者的差別,但這差別非常重 要!聚合關係數量較少、較持久,連繫關係則較常異動,甚至只存續 於一個操作當中;連繫關係也較富動態性,也更難從原始碼看出。由 於程式的執行期和編譯期結構有這種差異,可想而知:程式碼無法盡 數揭露系統的運作行為。系統的執行期結構必須多由設計者擔待,而 非程式語言;物件和型別的關係必須處理得更細心,畢竟執行期結構 的良窳全繫於此。

3.8 未雨綢繆(Design for Change)

能夠面對一再修改的舊需求和一再冒出的新需求,系統也必須隨 之因應,這是將再利用效用極大化的關鍵。想讓系統能因應如斯變 局,就得事先考慮好在它一生當中會有哪些演變。人無遠慮,必有近 憂。“改變”可能包括:重新定義類別、重新實作類別、修改客戶碼、

重新測試……,重新設計會波及軟體系統許多層面,若事先未規畫 好,代價可是非常高的。

(47)

統結構,不波及它處,讓系統在變局中更趨穩健。

(48)

第四章 模糊控制器簡介

4.1 自動控制系統的 Fuzzy 性問題

本世紀 40 年代發展起來的自動控制理論經歷了幾個時代之後已 日臻完美,幾十年來,它在實際應用中也取得了令人矚目的碩果。然 而,長期以來,以往的控制理論在處理現實世界中許多“亦此亦彼”

模糊現象的控制問題暴露了它的局限性,這也是現代控制理論在許多 複雜系統難以付諸實現的主要原因之一。對於控制問題而言,系統的 模糊性主要來自以下幾個方面:

1. 建立被控制對象數學模型時存在模糊性

實際上,對於一些複雜系統,真正掌握系統的動態特性一般是很 困難的。然而,為了運用經典或現代控制理論去實現系統的設計 和綜合,人們往往不得不採用一些簡便的方法去建立系統的數學 模型。但實際上,這種模型通常很難真實地描述系統特性。主要 原因有:模型的近似化(集中、定常參數、線性化等)、高階系統 的降階模型、大系統的人為分割、參數估計的誤差等等。可見這 些都包含著一定程度的模糊性。另一方面,不是所有的系統都能 實現這種模型(低階、線性、集中參數和非時變等)簡化處理的。

2. 測量信息存在模糊性

(49)

的檢測技術條件下是不可測或測不準的。倘若對被控對象的機制 不明,間接可測參數與直接不可測參數不能達到一一對應這種情 況下,構造出來的控制系統的模糊性是不言自明的。

3. 設計控制目標函數時存在模糊性

由於對一些複雜系統的動態行為不明瞭,或者為了控制系統實現 的方便,人們往往把系統的多項目標設計問題轉化為單一目標或 少項目標的函數極值問題,並常常忽略許多約束條件,即使給出 約束條件,也難免含有一定的模糊性。

4.2 Fuzzy 集合理論的問題求解

60 年代中期問世的模糊理論為描述客觀世界中的模糊現象奠定 了令人鼓舞的理論基礎。模糊集合理論並非提倡模糊思維,也沒有要 將我們的理論模糊化,或者說從本質上要去實現不精確的內含。相反 的,它是一種精辟的論說。模糊集合理論所指的模糊性,即不夠精確 性是針對在所劃分的類別與類別之間無明顯的歸屬到不歸屬的轉 折。事實上,在客觀世界中絕大部份的事物,說它們屬於某一類或不 屬於某一類都不存在明顯的分界線。

模糊集合理論中模糊度僅僅是用來突出人類思維、概念和語言的 一種元素,因為人腦通常是以不精確,非量化的模糊的方式進行思維 及推理的。然而,也只是由於這種方式使人們具備了在模糊信息的環

(50)

境下能夠概括有用信息,並集中主要相關的方面做出決策的能。而對 於這種處理和解決問題的方式,無論用古典的還是現代的控制理論都 是無法做到的。

實際上,複雜的過程常常是非線性和高維的多變數系統。為此,

很難用解析的數學方法去描述。相反,大量有關過程的知識只能用語 言的形式陳述。如果堅持要用既精確又有意義的數學方法刻劃這類過 程,其結果必將是隨過程複雜性的增加,刻劃的難度大幅度上升。而 且,正如 Zadeh 所提出的互克性原理[14][15],系統的複雜性愈高,

描述其精確且有意義的程度就愈低,直到一個臨界值,超過它,其精 度與有意義兩者是相互排斥的。

模糊控制技術是 70 年代初開始發展起來的。它產生的發展的主 要原因在於那些時變的非線性的複雜系統,無法獲得精確的數學模型 時,利用模糊控制取得較好的效果。因為這些過程有大量的以定性的 形式得到的先驗信息以及僅僅是語言上規定的性能指標,並且,有時 要求過程操作人員是系統的基本組成部份,所有這些都有不精確性的 特點。應用現代控制理論是很難實現控制的,由人去操作卻往往容易 做到。這是因為過程操作人員的控制方法是建立在直觀的和經驗的基 礎上,他們借實踐積累感性知識,“察言觀色”,採取適當的對策完 成控制任務。

(51)

模糊集合理論之所以發展如此迅速,是因為它符合了人類對客觀 規律的認識。當人們對一個問題的研究越深入,面臨的對象也就越複 雜,影響因素越多,所涉及到的細節也越多。當忽略了一些細節在壓 縮了的低維空間上進行觀察時,原本明確的概念就變得不確定和模糊 了。人類思維具有判別和處理不精確信自並從中得到具有一定精度結 論的能力。模糊集合理論能從數學的角度描述人腦的這種能力,從而 為問題求解之“智慧化”奠定了基礎。這也是它在控制、決策、學習、

分類、診斷等智慧化應用領域中獨佔熬頭的根本原因。

4.3 Fuzzy 控制工作原理初步介紹

某些工業過程難以實現自動控制,其困難可能來自難以對某一實 際過程建立數學模型,以及由於過程的非線性、時變特性或者難以測 量等等,然而這些難以自動控制的生產過程由人來控制卻往往工作得 很出色。

一般說來,操作人員的控制方法建立在直覺和經驗之上,於是把 人的控制經驗歸納為用定性描述的一組條件語句,然後利用模糊集合 理論將其定量化,使控制器得以接受人的經驗,模仿人的操作策略,

這樣就產生了模糊控制方法,這種方法可看成是一組探索式的判定規 則,它有如下特點:

1. 由於在人腦判定的過程中存在著不精確這個固有特性,使人的控

(52)

制動作往往不穩定、不一致以及主觀隨意,因此也就很難精確解 釋操作人員的控制行為。

2. 操作人員不但能對溫度、高度等簡單的度量作出反應,而且能觀 察諸如顏色、氣味等、複雜的度量模式,甚至對無法度量的事物 如相貌也可作出反應。這些觀察均有它的主觀性,但作出控制判 定正是基於這些帶有主觀性的量。

一個有實際經驗的控制工作者,通過對控制動作的觀察、以及與 操作人員交談討論,就能把操作人員的控制策略描述出來。所得到的 是一組用語言表達出來的定性的不精確的判定規則。應用模糊集合理 論,構成一組條件語句規則,稱為模糊控制規則,再運用計算機來模 擬近似人腦的推理的方法進行觀測與控制,從而構成模糊控制,這種 工業過程避開了用狀態方程式與轉換函數表達,其工作原理圖如下頁 圖 4-1 所示,具體控制過程是這樣的:

(53)

圖 4-1 模糊控制器工作原理圖

如被控對象為一水箱(水溫控制),人們已有這樣的控制經驗:“若 水溫偏高且溫度不太升則加一些冷水”;“若水溫偏高且溫度上升很 快則多加一些冷水”等等。這就是模糊控制規則,存在人腦中的“經 驗”,現已存放在“電腦”中。然而檢測溫度傳感器輸出是精確量,

要把它轉換成溫度高、偏高、偏低等模糊語句,就要 fuzzy 化。否則 無法運用“規則”,另外,“多加些冷水”;“少加些冷水”是 fuzzy 語句,最終得落實打開冷水閥門的大小,開啟幾度,精確量,故要 fuzzy 決策,確定控制輸出具體量。

最後,我們可以整理出模糊控制的幾個特點:

(a) 它不需要建立被控制對象的數學模型

(b) 它也能實現對時變非線性系統的控制

變成模糊形式

(Fuzzy 化)

精確量

傳感器 被控對象 執行機構

Fuzzy 控制規則

由模糊值計算 確定控制輸入

精確量

(54)

(c) 模糊控制對參數的變化有較強的適應性,對參數不敏感

(d) 控制質量高

(55)

第五章 模糊控制器運作流程

5.1 實作範例介紹

在說明模糊控制器的架構以及流程以前,首先必須說明一下所要 實作的控制器所要控制的受控端。如圖 5-1 所示:

距離 s

速度 v

圖 5-1 所要實作的受控端示意圖

假設有一輛汽車,已知距離目的地的距離是 s,另外在此時汽車 的瞬時速度為 v,以一般的常理來看,只要離目的地愈近,汽車的速 度 v 應該要愈來愈小,直到到達目的地時(也就是距離 s 為 0),汽車 速度正好為 0。

在此模糊控制器所要觀察的變數主要有二,一個是與目的地之間 的距離 s,另一個則是當時汽車的瞬間速度 v。而模糊控制器在完成 計算之後,應該要輸出一個明確值來控制汽車,當然,此明確值為汽 車新的速度 vout。

(56)

5.2 模糊控制器的設計

模糊控制器的基本架構如圖 5-2 所示:

模糊控制器

模糊變數 模糊變數

受控系統狀態或輸出(明確值) 明確的控制量

圖 5-2 模糊控制器的基本架構

一般而言,模糊控制器的原則性設計步驟如下:

1. 定義輸入及輸出變數

首先,要先決定受控系統有哪些操作狀況是必須被觀察、量測的。

另外,考慮哪些輸出動作是必須被控制的。

2. 定義各變數模糊化的條件

按實際狀況考慮輸入變數的量測及操作範圍,以便決定出每個模 糊變數的論域(universe of discourse)。然後安排每個變數的語言 表示事項及相對應的歸屬函數。

控制規則

模糊化

決策邏輯

解模糊化

受控系統

(57)

通常可以由操作人員的經驗和專家的知識,轉化成語言式的控制 規則。

4. 選擇解模糊化的方法

把推論完成的模糊輸出量轉換成實際的明確值(crisp value)這項 工作稱為解模糊化,解模糊化的方法有很多,而各種方法各有所 長,應針對不同對象加以選用。

5.3 控制器變數的決定與變數空間的模糊分割

模糊控制器的設計,首先必須定義輸入及輸出變數,以確定系統 哪些訊號作為輸入變數與輸出變數。並且再針對輸入變數與輸出變數 的空間做模糊分割。所謂的模糊分割就是將控制器變數的空間劃分為 若干個區域,對部份空間表示為模糊狀態,並以模糊歸屬函數來表示 這個模糊空間。例如一個控制器變數範圍是 0 至 60,若我們期望變 數值控制在 30,則可以用 5 個歸屬函數來進行模糊分割,如圖 5-3 所示:

很小 小 剛好 大 很大 1

0 10 20 30 40 50 60

圖 5-3 以 5 個歸屬函數模糊分割一維變數的空間

(58)

在此說明一下何謂歸屬函數? 在日常生活中,有許多的事物並無 法利用一般的二分法來斷言,例如以下兩個模糊命題:

模糊命題一:小王的薪水很高 模糊命題二:馬路上的空氣很差

像以上的兩個命題,就無法斷言是否是對的,而歸屬函數就可以利用 來充分解釋模糊命題,例如我們就可以將模糊命題一的歸屬函數如圖 5-4 這樣定義:

1

10k 35k 60k

圖 5-4 名稱為“小王的薪水很高”歸屬函數

圖 5-4 中,橫座標為薪水的值,縱座標為歸屬值。歸屬值的範圍為 0 到 1,假設小王的實際的薪水是每個月 35k,我們就可以說“小王的 薪水很高”這個模糊命題的“歸屬度”(也就是真實度)為 0.5。

同理,在圖 5-3 中,如果明確值是 33,則“剛好”的歸屬度是 0.7,

而“大”的歸屬度為 0.3,口語來說即是“不是說很大,差不多剛剛

(59)

好”,當然,口語的方法是見人見智的。

而這樣的口語化,我們可以稱之為“專家經驗”,既然是經驗,

有很多時候是無法公式化的,而歸屬函數的目的,就是可以將類似這 種的模糊命題給程度化,例如上述的“小王的薪水很高”,但是到底 有多高呢? 歸屬函數則可以告訴我們當小王的薪水多少時,此命題的 真實度有多少。如此一來,和一般二值化的傳統邏輯相比,模糊邏輯 則顯得有彈性多了。

在設計模糊控制器時,該選取多少個歸屬函數來分割變數空間並 沒有一定的標準,一般而言,選擇較多的歸屬函數時,在制定規則時 比較精細,因此比較靈活,但是會造成規則的複雜化及數量龐大,致 使模糊推論的時間太長,間接影響控制器的性能。因此為了考慮簡單 化且靈活性,通常選用 2~10 個歸屬函數來描述一個控制器變數。

至於變數的選擇方式,因為模糊控制器的控制規則,大都根據操 作人員控制經驗而提出的,而一般操作人員,大部份只能觀察到受控 對象的輸出變量與輸出變量的變化率。所以,在模糊控制器中,總是 選取誤差以及誤差的變化量,做為控制器的輸入變數,而將受控系統 控制量的變化做為控制器的輸出變量。以角度控制而言,控制器的輸 入變數就一定會選誤差角度與誤差角度變化率。

(60)

5.4 模糊控制器的控制規則

控制規則是模糊控制器的核心,做為判斷輸出的依據。基本上模 糊控制器是一個採用規則決策的系統,規則由系統控制要求或人的經 驗所制定。通常將代表控制規則的模糊條件語句,簡寫成一個表格型 式,稱為模糊控制決策表。由於模糊控制是經由語言形式的控制規則 所組成,因此可以很容易由控制規則了解控制器的動作,並且可以針 對系統某部份的響應加入特別加強的控制規則,進而改善系統控制情 況,也可藉著修改控制規則,將人類的經驗加入,來達到控制的目的。

所以模糊控制是屬於非線性型式的控制,在受控系統無法以線性數學 模式精確描述的情況下,經由適當調整控制規則,應該具有比傳統控 制方法更佳的控制性能。

模糊控制器的輸入,必須進行模糊化,其目的在於將一個明確值 轉化為一個模糊變數。模糊控制器的輸出,也是一個模糊變數。解模 糊化,就是將這個模糊變數轉化為一個明確量,送至受控系統上,解 模糊化的方法很多,較常用的,計有下列幾種:

1. 重心法(center of gravity defuzzifier)

2. 最大平均法(mean of maxima defuzzifier)

3. 修正型最大平均法(modified mean of maxima defuzzifier)

4. 中心平均法(center average defuzzifier)

(61)

5. 修正型中心平均法(modified center average defuzzifier)

最後再回到原本的問題,一開始也提到,所要觀察的變數為汽車 與目的地之間的距離 s 與汽車當時的瞬時速度 v,而最後要輸入給受 控端(也就是汽車)的變數為汽車的新速度 vout,也就是根據當時的 距離和速度來決定的新速度。

首先,先將汽車與目的地的距離 s 模糊化,我們將距離 s 如圖 5-5 表示:

很近 近 稍遠 遠 很遠 1

0 200 400 600 800 1000 1200

圖 5-5 距離 s 的模糊變數

圖 5-6 則是汽車速度 v 的模糊集合:

很慢 慢 中 快 很快 1

0 100 200 300 400 500 600

圖 5-6 汽車速度 v 的模糊變數

(62)

基本上,模糊控制器的輸出(也就是要給汽車的新速度)本身也 是一個模糊集合,只不過在最後解模糊化的部份在演算明確值時,是 利用到此輸出的模糊集合,而輸出的模糊集合如圖 5-7:

很慢 慢 中 快 很快 1

0 100 200 300 400 500 600

圖 5-7 控制器的輸出值 vout 的模糊變數

在決定好輸入與輸出的模糊變數之後,接下來是決定其控制規 則,模糊控制規則的制定是根據控制要求而來,其表示法如下:

第 i 個規則:if s is Ai1 and v is Ai2 then vout is Bi

命 題 部 推 論 部 i = 1,2,……n

參考文獻

相關文件

private void Page_Load(object sender, System.EventArgs e) {{. string dataSource

private void Page_Load(object sender, System.EventArgs e) {. string dataSource

通用類別(Generic Classes) - Code Reuse 的另一種發揮.. -

private void answerLB Click(object sender private void answerLB_Click(object sender,. System.EventArgs

afx_msg void OnLButtonDown(UINT nFlags, CPoint point). {……;

We present a new method, called ACC (i.e. Association based Classification using Chi-square independence test), to solve the problems of classification.. ACC finds frequent and

Triple Room A room that can accommodate three persons and has been fitted with three twin beds, one double bed and one twin bed or two double beds... Different types of room in

To convert a string containing floating-point digits to its floating-point value, use the static parseDouble method of the Double class..