H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具
物件導向? 青椒炒牛肉 青椒炒牛肉 不使用物件導向描述一件事 使用物件導向描述一件事 取出青椒 500 g,用刀切成細絲,過油 起油鍋、放入牛肉炒及青椒大火快炒 1 分半 拿出太白粉、水調在一起,這個稱為 芡汁。 將芡汁倒入鍋中攪拌,會產生黏稠現象 這叫芶芡 完成。 青椒 數量:500 g 處理:用刀切成細絲,過油 牛肉 數量:300 g 處理:切丁,用醬油、酒、黑醋醃製 芡汁 製作:太白粉調上適量的水 芶芡:將芡汁倒入鍋中 青椒處理好、牛肉處理好、芡汁製作好, 青椒、牛肉放入鍋中快炒 1 分半後,用 芡汁芶芡即可。
(這些數量及行為叫做 “屬性”與“方法”) 來描述整件事情是如何發生的。 (這部份的描述稱為“主程式”) 物件、屬性、方法 先定義好參與這件事的物品有哪些 (這些物品叫做 “物件”) 青椒炒牛肉 青椒 數量:500 g 處理:用刀切成細絲,過油 牛肉 數量:300 g 處理:切丁,用醬油、酒、黑醋醃製 芡汁 製作:太白粉調上適量的水 芶芡:將芡汁倒入鍋中 青椒處理好、牛肉處理好、芡汁製作好, 放入鍋中快炒 1 分半後用芡汁芶芡即可。 再定義這些物品所需的數量及行為 (這些數量及行為叫做 “屬性”與“方法”) 接下來就可用物品間的互動行為 來描述整件事情是如何發生的。 (這部份的描述稱為“主程式”) 物件導向優點:程式碼再用
1. 物件導向的基本概念 物件導向技術 (Object-Oriented Technique) 是繼結構化技術之後,系統開發上的新典範(Paradigm) 以物件模式來描述真實系統,並將資料抽象化(Data Abstraction)、封裝、繼承、同名異式、超荷的觀念融入物件導向的系統開發中
1.1 物件 (Object) 物件是一種可認知的東西,是物件導向的基本思維單位 我們認知下圖是一輛車,是因為聯想到: 車子是紅色。 車子有四個門。 車子有四個輪胎。
物件的範例 例如:Car1物件模擬一輛1800cc紅色四門的Sentra車子。Car1是物件的識別字,使用Car1識別字,可以在眾多模擬其他車輛的Car2、Car3、Car4….等物件中,識別出是哪一輛車輛物件。
物件的三種特性 狀態(State):物件所有「屬性」(Attributes)目前的狀態值 例如:車子的車型、排氣量、色彩等屬性 以程式來說,也就是資料部分的變數,可以簡單到只是一個布林值變數,也可能是另一個物件。 行為(Behavior):物件提供的服務,稱操作(Operations)或方法(Methods) 例如:車子可以發動、停車、加速和換擋等 程式語言是使用程序或函數來實作行為 識別字(Identity):每一個物件都擁有獨一無二的識別字來識別它是不同的物件 例如使用物件實際儲存的記憶體位址 (Reference),作為物件的識別字
1.2 類別 (Class) 具有相同結構及行為的物件所組成之集合 類別是物件經分類(Classification)或抽象化(Abstraction)所得的結果 也就是將物件抽象化,僅考慮相同性質特徵,排除其差異部分,將這些物件組成一個群體,稱為類別。
類別之範例
類別 以詹姆士、愛德華物件為例,他們有相似的行為與資訊結構,可表示成一個「人」的類別。
物件與類別 物件導向程式,都是以類別為基本單位所組成;在執行時的主體是物件,而非類別 class C { int i; //類別 C宣告了一整數變數 i } class D { public static void main(String[] args) { //程式開始的起點 C c1; // 根據類別C,宣告一個物件,名稱為 c1 c1 = new C(); // 以類別 C 為範本,產生一個物件c1 //兩者可和寫為 C c1 = new C(); c1.i = 10; System.out.println("c1.i = "+c1.i); 輸出結果: c1.i = 10
物件與類別之Java程式實例 class Account { private int balance; //宣告一帳戶餘額 void clearAccount() { balance = 0; } //清空帳戶餘額的 "方法" void deposit(int m) { balance = balance + m; } // 存錢的 "方法" int getBalance() { return balance; } // 顯示目前餘額的 "方法" } class E { public static void main(String[] args) { Account joe = new Account(); // 產生一個帳戶:joe Account wason = new Account(); // 產生一個帳戶:wason joe.clearAccount(); // 將 Joe 的帳戶餘額清空 wason.clearAccount(); // 將 Wason 的帳戶餘額清空 joe.deposit(300); // Joe 存了 300 元 wason.deposit(500); // Wason 存了 500 元 // 顯示 Joe, Wason 目前的帳戶餘額 System.out.println("Joe has " + joe.getBalance() + "dollars."); System.out.println("Wason has " + wason.getBalance() + "dollars."); 輸出結果: Joe has 300 dollars. Wason has 500 dollars.
1.3 封裝 (Encapsulation) 物件導向技術,將資訊(屬性)與操作此資訊的函數(方法)包裝成一個物件,稱為封裝。 將物件的實作細節隱藏,使其與外界環境隔離,而只允許該物件所包含之操作修改其資訊,稱為資訊隱藏(Information Hiding)。 使用物件時,僅需知道物件提供何種操作,而不需知其內部之資訊或行為是如何表達或執行。 封裝之特性使物件導向的系統較容易維護。
Java的封裝 將物件中資源(資料或方法)的存取分為幾個等級,以管理某些資源隱藏在物件中,某些資源開放給外界使用。 Public (公開): 將物件內部的資源開放給外界使用。 Private (私有):資源的所有權完全屬於該類別,只有在物件內部才可對其作存取動作。任何外部的存取均會導致錯誤發生。 Protected (保護):在所屬的 package 中是被視為 public 資源;但是在其他的 package 中,則只被繼承的子類別使用。 Default Access (預設存取)或Package(類別庫):在所屬的 package 中是被視為 public 資源;但是在其他的 package 中,則會被視為是 private 資源而無法被使用。
封裝資料之Java程式實例 class C { private int i; // 私有資料 public int j; // 公開資料 int k; // 預設存取資料 } class D { public static void main(String[] args) { C c = new C(); c.i = 5; // Error! c.i 是 private資料,禁止存取! c.j = 10; // OK! c.k = 15; // OK!
封裝方法之Java程式實例 class Account { private int balance; // 私有資料 void public clearAccount() { balance = 0; } // 公開方法 void deposit(int m) { balance = balance + m; } // 預設存取方法 private int getBalance() { return balance; } // 私有方法 } class D { public static void main(String[] args) { Account joe = new Account(); joe.clearAccount(); // OK! joe.deposit(300); // OK! System.out.println(“Joe has ” + joe.getBalance() + “dollars.”); // ERROR! 使用私有方法
1.4 繼承(Inheritance) 承接所有父類別 (Parent Class) 所有屬性及方法,並可加以改造的特性。 以男人和女人物件為例,將相同的部分抽出,一般化成一個更上層的類別(父類別),稱為「人」類別。 物件導向技術中,繼承概念對軟體工程有革命性的影響,如達成程式碼再用(Reuse)與減少重複描述、產生可靠度較高的軟體等。
繼承之實例 學生和老師都是人,可先定義Person類別來模擬人類,然後擴充Person類別建立Student和Teacher類別,模擬學生和老師
繼承之Java程式實例 執行結果: The value of d is 5 The value of e is 7 class C { private int i; public void setInfo(int x) { i = x; } public int getInfo() { return i; } } class D extends C {} // 類別 D 繼承類別 C class E extends C {} // 類別 E 繼承類別 C class F { public static void main(String[] args) { D d = new D(); E e = new E(); d.setInfo(5); e.setInfo(7); System.out.println("The value of d is "+d.getInfo()); System.out.println("The value of e is "+e.getInfo()); 執行結果: The value of d is 5 The value of e is 7
覆寫(overriding) 子類別將繼承自父類別來的屬性或方法,重新定義的動作 變數覆寫 方法覆寫 將繼承自父類別的變數遮蓋起來。(在父類別中的變數宣告並不會因此消失,它只是隱藏起來而已) 方法覆寫 將繼承自父類別的方法遮蓋起來。 這種設計讓我們在繼承類別時,可將不符合需求的方法加以改寫,如此一來,子類別的使用者就不會也不能看到及使用父類別中的方法,以達到重新設計的目的。
變數覆寫之Java程式實例 class C { int i = 10; } class D extends C { int i = 5; class E { public static void main(String[] args) { D d = new D(); System.out.println("d = "+d.i); 執行結果: d = 5
方法覆寫之Java程式實例 class C { void f(String s) { System.out.println("f in class C: "+s); } class D extends C { System.out.println("f in class D: "+s); // 父類別的方法被覆寫! class E { public static void main(String[] args) { D d = new D(); d.f("hello"); 執行結果: f in class D: hello
1.5 同名異式(Polymorphism) 又稱「多型」 相同的方法名稱,卻定義不同的實作(implementation) 目的:希望簡化系統發展的複雜性,並增加其彈性。 在人類的思維中,對於同一種工作,就算對象不同,也會使用相同名稱的操作,例如:
同名異式又稱為動態多型 多型在程式呼叫一方法時,以動態連結(Dynamic Binding)的方式,來判斷當時被呼叫物件所屬的類別,以決定執行哪一實作 動態多型是建立在繼承的架構上:
同名異式之Java程式實例 執行結果: Triangle! Rectangle! Circle! abstract class Shape { public abstract void f(); } class Triangle extends Shape { public void f() { System.out.println("Triangle!"); class Rectangle extends Shape { System.out.println("Rectangle!"); class Circle extends Shape { System.out.println("Circle!"); class E { public static void main (String[] args) { Shape[] s = new Shape[] { new Triangle(), new Rectangle(), new Circle() }; for (int i=0; i<s.length; i++) { s[i].f(); } 執行結果: Triangle! Rectangle! Circle!
1.6超荷(或稱過載,Overload) 在同一類別中有相同名稱的操作,依參數個數及參數資料型態來判斷要使用哪一個操作,又稱靜態多型。 例如: class C { int add(int i, int j) { return i + j; } int add(int i, int j, int k) { return i + j + k; } String add(String i, String j) { return i + j; } } class D { public static void main(String[] args) { C c1 = new C(); System.out.println("3 + 10 = "+c1.add(3,10)); System.out.println("1 + 2 + 5 = "+c1.add(1,2,5)); System.out.println("'abc' + 'xyz' = "+c1.add("abc","xyz")); 執行結果: 3 + 10 = 13 1 + 2 + 5 = 8 'abc' + 'xyz' = abcxyz
2. 物件導向分析與設計及塑模工具 統一塑模語言(Unified Modeling Language, UML) 可以讓我們使用圖形描述系統來建立模型 是Rational 公司整合Booch、Rumbaugh 與Jacobson 三種方法,提出的物件導向塑模工具
UML的4+1觀點 對於複雜的軟體系統,需要透過一組UML圖形才能完整描述系統的所有資訊 Kruchten’s的4+1觀點能夠幫助我們呈現不同種類UML圖形在描述整個系統模型時扮演的角色,稱為「觀點模型」(View Model)
4+1觀點 設計觀點 處理流程觀點 實作觀點 部署觀點 使用個案 觀點
使用個案觀點(Use Case View) 從系統外部的使用者角度,來表達系統要做什麼,並不涉及系統的軟硬體架構 由描述系統行為的使用個案組成 與其他4個觀點都相關,所以稱為+1觀點 UML:使用個案圖。 設計觀點 處理流程 觀點 實作觀點 部署觀點 使用個案
設計觀點(Design View) 描繪系統的靜態結構以及動態行為,以做為系統所應提供之功能的解答 重點在系統之類別、介面、物件的合作等設計問題 UML:類別圖、物件圖、狀態圖和互動圖 (循序圖、溝通圖、時序圖、互動概觀圖)。 設計觀點 處理流程 觀點 實作觀點 部署觀點 使用個案
處理流程觀點(Process View) 描繪系統非功能需求的的績效(Performance)、產出(Throughput)與可擴充性(Scalability) 著重表達系統內部的處理程序,如同步機制之執行緒(thread) UML:活動圖。 設計觀點 處理流程 觀點 實作觀點 部署觀點 使用個案
實作觀點(Implementation View) 以程式設計者角度的觀點 著重於程式碼管理的模組與元件 以模組或元件來顯示設計觀點的物件,是在哪一個模組或元件中實作。 UML:元件圖。 設計觀點 處理流程 觀點 實作觀點 部署觀點 使用個案
部署觀點(Deployment View) 從系統工程師觀點呈現的系統 表達系統執行時,各個組成元件的實際佈置與安裝,強調系統執行環境的硬體拓撲上各節點(Nodes)之配置。 UML:部署圖。 設計觀點 處理流程 觀點 實作觀點 部署觀點 使用個案
物件導向分析與設計之塑模 上述五個觀點,配合物件導向分析與設計(含需求分析、系統分析與設計),可分為五種塑模: 使用個案塑模(需求塑模):使用個案圖、活動圖、藍圖與資料詞彙 物件結構塑模:類別圖與物件圖 物件互動行為塑模:循序圖與溝通圖 使用者介面塑模:介面結構圖、介面藍圖、介面詞彙、循序圖與狀態圖 系統元件與結構塑模:元件圖與部署圖
套件圖 圖9-7 物件導向塑模活動及塑模工具
物件導向核心工作流程與塑模工具
系統 分析與設計和塑模工具: 結構化vs.物件導向
3. UML塑模工具 UML塑模工具(UML Modelling Tool),可幫助系統開發者使用UML圖形進行物件導向分析與設計,快速建立軟體系統所需的模型。 依使用者的授權方式,可分為商業和免費版本UML塑模工具。 簡介影片: UML Video 01: Choosing the right UML Package
商業版本的UML塑模工具 提供較強大功能 常見商業版本的UML塑模工具,如下: 很多都提供Community社群版,可以讓非商業用途的使用者免費使用,不過,其功能會打一些折扣,而且通常都需要線上註冊啟動後才能使用。 常見商業版本的UML塑模工具,如下: IBM Rational Software Architect(RSA) Microsoft Visio Astah UML Visual Paradigm for UML(VP-UML) Enterprise Architect…
免費版本的UML塑模工具 Open Source(開放原始碼) 的免費塑模工具,和一些非商業用途使用者可全功能免費使用的UML塑模工具,例如: StarUML ArgoUML Umbrello BOUML Software Ideas Modeler…
Software Ideas Modeler 官方網站: http://www.softwareideas.net/ 下載:http://www.softwareideas.net/en/download 安裝: UMLVideo02: Install and Run Software Ideas Modeler