面向?qū)ο缶幊?/em>:以類或?qū)ο笞鳛榻M織代碼的基本單元,將封裝、抽象、繼承、多態(tài),作為代碼設(shè)計和實現(xiàn)的基石。
面向?qū)ο缶幊陶Z言:支持類或?qū)ο蟮恼Z法機制,能方便的實現(xiàn)上述四大面向?qū)ο筇匦缘木幊陶Z言。
封裝/抽象/繼承/多態(tài) 可以解決的編程問題
封裝(Encapsulation)
封裝也叫做數(shù)據(jù)訪問保護。類通過暴露有限的訪問接口,授權(quán)外部僅能通過類提供的方式來訪問內(nèi)部信息或數(shù)據(jù)。
封裝的意義:如果對類中的屬性訪問不做限制,任何代碼都可以訪問、修改類中的屬性,這就會造成數(shù)據(jù)的不可控,屬性可以隨意的被修改。此外,通過有限的方法暴露必要的操作,也能提高類的易用性。如果把類的屬性都暴露給類的調(diào)用者,他需要對業(yè)務(wù)細(xì)節(jié)有足夠了解才能正確操作這些屬性。
抽象(Abstraction)
抽象說的是如何隱藏方法的具體實現(xiàn),讓調(diào)用者只需要關(guān)心方法提供了哪些功能,而并不需要知道這些功能是如何實現(xiàn)的。
繼承(Inheritance)
繼承用來表示類之間is-a的關(guān)系。
繼承的意義:繼承最大的好處是代碼復(fù)用。假如兩個類有相同的屬性和方法,可以將相同的部分,抽取到父類中,這樣兩個子類就可以重用父類中的代碼。
過渡使用繼承,繼承層次過深,會導(dǎo)致代碼可讀性、可維護性變差。
多態(tài)(Polymorphism)
多態(tài)是指,子類可以替換父類,在實際代碼運行中,調(diào)用子類的方法實現(xiàn)。
多態(tài)的意義:提高代碼的擴展性和復(fù)用性,是很多設(shè)計模式、設(shè)計原則、編程技巧的代碼實現(xiàn)基礎(chǔ)。
面向過程與面向?qū)ο?/h3>
什么是面向過程編程
面向過程編程以方法、函數(shù)作為組織代碼的基本單元,以數(shù)據(jù)(成員變量、屬性)與方法相分離為最主要特點。面向過程風(fēng)格是一種流程化的編程風(fēng)格,通過拼接一組順序執(zhí)行的方法來操作數(shù)據(jù)完成一項功能。
面向過程與面向?qū)ο笞钪饕膮^(qū)別是,代碼的組織方式不同。面向過程風(fēng)格的代碼被組織成了一組方法集合及其數(shù)據(jù)結(jié)構(gòu),方法和數(shù)據(jù)結(jié)構(gòu)定義是分開的。面向?qū)ο箫L(fēng)格代碼被組織成一組類,方法和數(shù)據(jù)結(jié)構(gòu)被綁定一起,定義在類中。
面向?qū)ο缶幊痰膬?yōu)勢
1.更能應(yīng)對大規(guī)模復(fù)雜程序的開發(fā);
- 大規(guī)模復(fù)雜程序中,處理流程并非一條單一的主線,而是錯綜復(fù)雜的網(wǎng)狀結(jié)構(gòu);
2.具有更加豐富的特性,更加易擴展、易復(fù)用、易維護;
- 利用了封裝、抽象、多態(tài)、繼承;
3.更加人性化、高級且智能。
- 面向過程編程更加貼近機器的思維方式,而面向?qū)ο缶幊谈淤N近人;
錯誤的面向?qū)ο缶幊?/h3>
1.濫用getter、setter方法
public class ShoppingCart{
private int itemsCount;
private List<Item> items = new ArrayList<>();
public void setItemsCount(int itemCount) {
this.itemCount = itemsCount;
}
public List<Item> getItems() {
return this.items;
}
}
public class ShoppingCart{
private int itemsCount;
private List<Item> items = new ArrayList<>();
public void setItemsCount(int itemCount) {
this.itemCount = itemsCount;
}
public List<Item> getItems() {
return this.items;
}
}
這里定義了private變量,但是提供了public setter方法,這就跟將這個屬性定義為public沒什么區(qū)別了。
所以,我們不應(yīng)該暴露不該暴露的setter方法。
對于items屬性,雖然沒有提供setter方法,但因為它是一個集合容易,外部可以拿到這個容器后,修改里面的數(shù)據(jù)。這就會造成items和itemsCount的不一致。
所以,如果需要知道items里面有什么,我們需要通過返回不能被修改的容易方法。
public List<Item> getItems() {
return Collections.unmodifiableList(this.items);
}
2.濫用全局變量和全局方法
常見的全局變量:單例類對象、靜態(tài)成員變量、常量等;
全局方法:靜態(tài)方法,常用的Utils類。
下面通過Constants類的定義來探討全局變量的利與弊:
public class Constants {
public static final String MYSQL_ADDR = "mysql_addr";
public static final String MYSQL_DB = "db_name";
// ...更多常量定義...
}
把所有的常量,都集中放到一個Constants類中,不是很好的設(shè)計:
- 影響可維護性:類會越來越大。
- 增加代碼編譯時間:這個類會被很多別的類依賴,每次修改該類,都會導(dǎo)致依賴它的類文件重新編譯。
- 影響代碼復(fù)用性:假如在另一個項目中復(fù)用本項目某個類,但這個類又依賴Constans類,即使只用到Constants類中的一小部分變量,也需要把整個類都引入。
如何改進?
- 拆分;
- 不單獨使用常量類,而是哪個類用到某個常量,將其定義到這個類中。