2016年1月8日 星期五

物件導向設計:從需求轉程式 Object Oriented Design (OOD) : from Requirements to Code

 

二次讀物件導向,才發現這個典範的厲害,只能說這些想法不寫個三五年程式是無法體會的呀。學校課程大多把OO放在入學的第一年,要體會這些設計理念實在太苛刻了一點XD 廢話不多說,開始整理學習囉^^ Modeling First Coding Later!

2016.1.8 初版
2017.8.9 二版





一、物件導向簡介


物件導向設計 (Object-Oriented Design) 是一種思維,透過強調可重複性,一定程度上解決了軟硬體環境逐漸複雜而難以維護的問題。

物件導向程式設計中包含各種獨立而又互相呼叫的物件,以物件模式描述真實系統,並將「抽象化 (Abstraction)」、 「封裝 (Encapsulation)」 、 「繼承 (Inheritance)」 、 「多型 (Polymorphism)」的觀念融入系統開發中。

物件導向之所以流行的原因,是因為其增進程式設計師工作的效率以及軟體的品質,降低物件之間的耦合力、提高物件的內聚力,讓程式碼重複利用。有一種說法是說 : 「往後改動最少的程式碼,就是最好的程式碼。」,在物件導向之下十分契合這個理念,目前物件導向在大型項目設計中廣為應用。






二、物件與類別  Object and Class



1. 物件 (Object)


物件 (Object) ,用白話文來理解的話稱為「東西」,是物件導向的基本思維單位,為具有狀態、行為與識別實體 (Entity) ,其行為會影響其狀態。

物件之組成包括:

  • 屬性 (Attributes)
  • 操作 (Operations) 或稱方法 (Methods) 

物件大致的行為:

  • 物件有生命週期,會「產生」和「消滅」
  • 物件具有其內部狀態(),同一類別的不同物件,其的內部狀態可能都不一樣
  • 物件可以接收訊息,並依據訊息的參數以及該物件的內部狀態,做出反應,並可能因而改變該物件的內部狀態


[用心去感覺] 實例 (instance) 與物件 (object) 的差別

類別中之任一物件則稱該類別之實例 (Instance),因此物件與實例一般情況可視為同義詞,但還是須了解兩者間的微妙不同,實例僅僅指某一類別之實體化的物件。 


2. 類別 (Class)


類別為物件經分類 (Classification) 或抽象化(Abstraction) 所得的結果,也就是剔除物件間的差異而只考慮其相同性質,並將這些物件組成一個群體。以物件導向寫作程式時,寫作的主體是類別。類別定義了所有屬於該類別的物件的特性。

  • 表達物件內部狀態的變數,又被稱為成員變數 (member variable) 
  • 表達物件可以使用的操作,又被稱為方法 (method)、成員函數(member function) 
  • 表達這些變數和操作的使用方法



[用心去感覺] 類別 (class) 與物件 (object) 的差別

  • 類別(Class):定義了一件事物的抽象特點。類別的定義包含了資料的形式以及對資料的操作,屬性為靜態的。
  • 物件(Object):類別的實例,可執行,是屬於動態的。



[用心去感覺] static 和 final

成員 (member) 宣告時若使用關鍵字 static 修飾,該成員變成屬於類別 (class) 而非物件 (object)。

  • Static Attribute : 類似於全域變數
  • Static Operation : 可不藉實例直接以類別名稱呼叫

成員 (member) 宣告時若使用關鍵字 final 修飾,表示該成員為常數 (constant) 。

  • final Attribute : 不能重新給值
  • final Operation : 繼承 (inherit) 後不可被改寫 (override) 








三、物件導向的特色:封裝、繼承、多型


所謂「物件導向的特色」,指的是物件導向的三個機制,三者缺一不可,此三個機制分別為封裝(encapsulation)、繼承(inheritance)、多型(polymorphism)。

  1. 封裝 (Encapsulation) : 隱藏某一方法的具體執行步驟,把過程和資料包起來,對資料的操作只能通過已定義的界面
    • 介面 (Interface):用以定義物件之外觀行為。
    • 實作 (Implementation):用以存放抽象化結果及描述如何達成外觀行為。
  2. 繼承 (inheritance) : 子類別會繼承父類的方法和屬性。子類別比父類別要更加具體化,如鸚鵡之於鳥。
  3. 多型 (Polymorphism) : 定義具有不同功能但名稱完全相同之方法或屬性的類別。
    • 靜態多型 (Static polymorphism/Overloading) : An invocation can be operated on arguments of more than one type.
    • 動態多型 (Dynamic polymorphism/Overriding) : A same operation may behave differently on different classes.

overloading 範例

class Calculation {  
  void sum(int a,int b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  

  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  // 30
    obj.sum(20,20);     //40 
  }  
}  

overriding 範例

class Animal {    
   public void move(){
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {

   public void move() {
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal(); // Animal reference and object
      Animal b = new Dog(); // Animal reference but Dog object

      a.move();//output: Animals can move

      b.move();//output:Dogs can walk and run
   }
}


[補充] Overriding

Override 發生在繼承關係間。重新定義從父類別繼承下來的方法。除了方法名稱必須要與想Overriding 的方法一樣之外,方法的回傳值型態與參數形式也必須與父類別一模一樣。

可在方法前加上 @Override 這個註釋 (annotation),提示編譯器以避免程式行為不如預期。


[用心去感覺] 封裝 (Encapsulation) 和抽象 (Abstraction) 的差別

  • 抽象:對一件事物只了解其外在,而不需了解其內部構造或實作方法
  • 封裝:抽象的一部分的策略,封裝著重於強調對該類別的操作只能由「定義的界面」。






四、關係 (Relationship)



1. Dependency (Uses-a)


the weakest relationship between classes. No need to hold a reference. 



通常是用在這兩種操作上 : <<use>> 、 <<create>> ,例如:



2. Association (Has-a)


stronger than dependency. Need to hold a reference.


  • Association name :  for example, write between professor and book
  • Role name : for example, author and textbook
  • Association Qualifier : keyed or indexed, 有用到 hash 的場合!
  • Association Class : An association has attributes associated with the association itself

Association name 和 Role name 示範


Association Qualifier 示範


Association Class 示範





3. Aggregation (Owns-a, Is-part-of, Is-a)


a stronger version of association.

  • Aggregation (Owns-a) : A “weak” form of aggregation
  • Composition (Is-part-of) : A Composition adds a lifetime responsibility to Aggregation
  • Delegation : An object forwards an operation to another object that is part of or related to the first object for execution. For example, stack and list.
  • Generalization (Is-a) : Generalization is the strongest relationship. 


Composition (Is-part-of) : lifetime responsibility 範例






五、抽象類別 : Abstract class 和 Interface


Abstract class 和 Interface 是兩種定義抽像類別的方式,它們之間有很大的相似性。但是對於它們的選擇卻又往往反映出對於問題領域中的概念本質的理解、對於設計意圖的反映是否正確、合理,因為它們表現了概念間的不同的關係(雖然都能夠實現需求的功能)。


1. 抽象類別 Abstract class


用在整個繼承體系的最上層(Inheritance),用來定義出整個繼承體系該有哪些方法,子類別可以對這些方法加以修改(override),或維持和抽象類別 (abstract class) 相同的功能。Design Pattern 中的 template method,factory method...等就是用這種手法。一個類別只能使用一次繼承關係。但是,一個類別卻可以實現多個介面 (interface)。

原文定義 : The main purpose of an abstract class is to define a common interface for
its subclasses.


2. 介面 Interface


用在當一個物件須和其他物件共同合作時(Composition),為了確保其他物件有我想要的方法,所以定下介面要該物件遵守,在Design Pattern到處可以看到這種應用,如strategy,bridge,prototype...。

原文定義 : The main purpose of an abstract class is to define a common interface for
its subclasses.



[用心去感覺] 介面可以達到多重繼承的效果

Java不能多重繼承,但介面 (interface) 可以達到多重繼承的效果,這個效果準確來說是:「多重繼承時通常其中一個基底類別作為private實作體,而其它的用以表現完全的抽象介面。」






六、需求轉物件導向設計



1. 由需求中找出類別和屬性


從每個需求敘述中找出名詞來,每個名詞都是類別屬性的候選者。篩選出類別可能含有行為及屬性,若該名詞不具備方法及屬性,則可能是某類別的屬性之一。


2. 找出類別的方法


找出需求敘述中的動詞(is、was、have),這將會是方法的候選者,且透過需求敘述你可以再將這些動詞與上一步驟所找出的名詞結合。


3. 繪製類別圖


藉由前兩個步驟加上前幾章的物件導向觀念繪製出類別圖。


4. 驗證你的需求


重新驗證需求中的每個敘述,並檢討可能遺漏的必要功能。





七、練習題


[exercise 1] 

A person has a name, address, and social security number. A person may charge time to projects and earn a salary. A company has a name, address, phone number, and primary product. A company hires and fires persons. Person and
Company have a many-to-many relationship.

There are two types of persons: workers and managers. Each worker works on many projects; each manager is responsible for many projects. A project is staffed by many workers and exactly one manager. Each project has a name,
budget, and internal priority for securing resources.

A company is composed of multiple departments; each department within a company is uniquely identified by its name. A department usually, but not always, has a manager. Most managers manage a department; a few managers are not assigned to any department. Each department manufactures many products; while each product is made by exactly one department. A product has
a name, cost, and weight.

[exercise 1 Answer]







References


wiki - 物件導向程式設計
https://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1

軟體開發的天空 - 系統設計的起點:如何將需求轉為物件導向的設計
https://www.dotblogs.com.tw/jameswu/2008/06/26/4388

Hank to hanker - [OO] OO物件導向速記
http://whhnote.blogspot.tw/2010/07/oo-oo.html

物件導向系統分析與設計 吳仁和 著
http://www.bestwise.com.tw/_trial_files/b2170a/ch03.pdf

Ruby Programming/Syntax/Classes
https://zh.wikibooks.org/zh-tw/Ruby_Programming/Syntax/Classes#.E9.A1.9E.E5.88.A5.E6.96.B9.E6.B3.95.28Class_Method.29

資料識別(Data Identity)
http://openhome.cc/Gossip/HibernateGossip/DataIdentity.html

Java 快速導覽 - 物件導向概念 static 成員
http://pydoing.blogspot.tw/2010/11/java-static.html

[OO概念]封裝,繼承,多型
http://handsome-bridge.blogspot.tw/2013/02/oo.html








技術提供:Blogger.