標籤:物件導向 原廠模式 設計模式 可擴充 編程
在剛開始學習一門物件導向語言的時候,我們是這樣寫代碼的:
我們會先寫一個小狗類,然後new它,最後調用它的方法實現功能。
例如:
Dog d=new Dog();//造個小狗
d.shout();//小狗看到stranger會叫
看得懂這段代碼,說明你的面向過程語言基礎學的不錯~~~~~
好的,這段代碼先到這裡,我們先來談談物件導向的特徵:
1,抽象:
首先想想我們在什麼時候用到抽象?
a.當我在設計一個系統的時候,我需要把一些東西歸類,比如,小狗,小貓,這些都會做一個animal類,然後讓小狗小貓繼承這個animal.這是基本的類抽象
b.還有一類抽象,比如我們寫個介面,讓一個類去實現這個介面,這是介面的抽象;(抽象類別的抽象和介面的抽象是一樣的,都沒有方法體,都要子類去具體實現);
c.類的成員變數使用超類或介面:
當某個類作為另一個類C的成員變數的時候,而這個子類又有諸多變化,這時我們就要考慮將這個變化的部分做成多個子類,並且將這多個子類抽象出來一個父類,將這個父類作為類C 的成員變數。
比如,我現在有個很多收費策略,然後在類C中有一個要調用計算收費的方法,但是因為調用時的諸多情況,我必須在調用時動態確定使用哪種收費策略,所以,在定義這個C的成員變數時,我們就要使用抽象出來的父類了,即為眾多的策略定義一個父類或介面。
這時情況又和上面的小貓小狗的情況一樣了。而且預先設計中的抽象和重構方法時的抽象目的是相同的,都是為了系統的擴充性,易修改。
總的來看,抽象起到了一個概括的作用,就像拿著一條摸起來涼涼的,張的長長的,吐著舌頭的東西問你,知道這是什麼嗎?你不確定這是哪種蛇,但是,你會非常肯定的回答:這是條蛇!這樣的回答雖然不準確,但是卻給了你百度的時間,等你百度過後,你就可以說:這是條@#[email protected]#蛇。。。。
2,封裝
封裝能帶來什麼好處呢:
1,首先,想想你使用過的實體類,你能很快寫出這個是學生的ID,這個是教師的ID。。。這裡,封裝實體的資料,起到了一個打包的作用,將屬性綁定到了類上,方便尋找和使用,上面列舉的是對於屬性的封裝。類中也有方法啊,所以,同樣,也有方法的封裝。
2,回想設計模式,有些對象的建立過程我們是無需參與的:例如,在單例模式中,我們將類之建立一個執行個體的過程交給類本身來處理,將類的建立封裝在了類裡面,避免了建立多個執行個體; 還有我們熟悉的各種原廠模式,我們將對象的建立遷移到了具體的工廠類裡面,去除了選擇問題。
3,對類行為的封裝
回想一下命令模式,我們把各個命令做成類,將請求操作的對象和執行操作的對象分開了,接觸了這裡的緊耦合。
3,繼承
在物件導向的設計中,我們是免不了使用繼承的,首先,來看一下公認的使用繼承帶來的那些好處:
a.基本好處:
可以繼承父類的屬性和方法,獲得父類的行為。例如,我們在使用模板方法的時候,將重複的東西都放到父類,子類只需在繼承父類的基礎上做一個很小的變更就ok了。
b.通過繼承達到“類型匹配”
在裝飾者模式中,我們讓服飾類去繼承people,這在現實中是不可理喻的,但是在設計中,正是通過這個繼承,讓我們可以在形象展示中層層調用父類的方法,達到一個裝飾的效果。感覺這個模式設計的非常酷!!!
但是,繼承的後果你想過嗎?
1,多繼承的後果:C++強大的多繼承為代碼的複用提供了很大的方便,但是也帶來了很多問題,比如多繼承的二義性問題,還有繼承關係的混亂問題;
2,為了複用而使用的繼承會給維護增加的子類帶來困難,因為子類很可能不具有它從父類繼承的方法,而且它也無法屏蔽從父類裡面繼承的方法。就像是富二代老爸想給兒子安排接手自己公司可是兒子卻偏偏想去玩兒音樂。如果子類不需要父類的方法或者根本不能去實現父類的方法,這就讓繼承關係帶來了一個非常尷尬的事情。
面對繼承可能帶來的後遺症,所以,我們才才有了後來的提倡使用組合取代繼承。
4,多態
如果說物件導向為什麼可擴充性這麼強,而且非常靈活的原因,感覺多態起了很大的作用。
首先,回到我們開始的小狗的問題上:
Dog d=new Dog();//造個小狗
d.shout();//小狗看到stranger會叫
如果有一天,我不想聽小狗叫了,我想聽貓叫了,這時,可能我們會這樣寫:
//Dog d=new Dog();//造個小狗
//d.shout();//小狗看到stranger會叫
Cat c=new Cat();
c.shout();
但是,過了兩天,我又想聽雞叫了,這時,你可能又把小貓的代碼注釋掉,改成雞叫的代碼,但是,作為一個程式員,你要認識到,一段相似的代碼寫到第三遍了,那麼一定是設計的有問題。
這時,多態的作用就顯示出來,這也是為什麼在編程中一直強調的寫法:將父類的引用指向子類的對象。
如果我們使用了這種寫法:
Animala=new Cat();
a.shout();
那麼,我們日後的變更將更加方便,當我們要變更具體的實現的時候,只要稍加改動就好啦!
另外,還有重寫,重載等多態的表現,但是還是覺得上面的最經典。
PS:最近在學習Java+Head first,感覺這是我真正邁入物件導向大門的開始~~~
物件導向的重新思考