面向?qū)ο蟮母拍?/strong>
萬(wàn)物皆對(duì)象。對(duì)象的實(shí)質(zhì)是屬性和行為。
類(lèi)是具有共同屬性和行為的對(duì)象的集合。類(lèi)定義了對(duì)象的屬性和方法。
面向?qū)ο缶幊桃詫?duì)象和類(lèi)為主體,基本組成要素是類(lèi)和對(duì)象。
類(lèi)
是具有相同特征的對(duì)象的抽象,是一種數(shù)據(jù)類(lèi)型。
基本結(jié)構(gòu)
- 屬性:對(duì)象數(shù)據(jù)的描述
- 方法:對(duì)象的行為
- 構(gòu)造方法:用于實(shí)例化對(duì)象
- 內(nèi)部類(lèi):在類(lèi)中聲明的類(lèi)(inner class)
- 塊:分靜態(tài)塊與實(shí)例塊
- 類(lèi)的聲明:private,default final,abstract,synchronized class 類(lèi)名 { 主體 }
對(duì)象
是客觀實(shí)體的映射,在程序設(shè)計(jì)上對(duì)象是類(lèi)的具體示例
面向?qū)ο笕笠?/strong>
封裝
指利用抽象數(shù)據(jù)類(lèi)型把數(shù)據(jù)和操作封裝在一起,用戶(hù)只能看到對(duì)象的外部信息,對(duì)象的內(nèi)部細(xì)節(jié)是隱藏的。
一方面封裝表示對(duì)象的屬性和方法是一個(gè)整體,是獨(dú)立的,另一方面它表示對(duì)象的內(nèi)部是隱藏的。
可以將青少年封裝成一個(gè)類(lèi),有姓名、性別、年齡的屬性,以及吃、睡的行為,如下:
class Teenagers {
private String name;
private String sex;
private String age;
public void eat() {
}
public void sleep() {
}
}
繼承
反映了兩個(gè)類(lèi)之間的一種關(guān)系,當(dāng)一個(gè)類(lèi)擁有另一個(gè)類(lèi)的所有屬性和方法時(shí)稱(chēng)這個(gè)類(lèi)繼承了另一個(gè)類(lèi),這兩個(gè)類(lèi)具有繼承的關(guān)系,是一種創(chuàng)建新類(lèi)的機(jī)制.
學(xué)生也是青少年,所以可以繼承青少年的屬性及行為;另一方面,他有自己的屬性和行為。如下,學(xué)生有作業(yè)的屬性,學(xué)習(xí)的行為:
class Student extends Teenagers {
private Map<String,Object> homework;
public void study() {
}
}
多態(tài)
就是多種狀態(tài),即同一個(gè)實(shí)體具有多種形式。多態(tài)一般在程序運(yùn)行的過(guò)程中表現(xiàn)出來(lái),即同一種類(lèi)型在不同條件下表現(xiàn)不同的結(jié)果。多態(tài)也稱(chēng)為動(dòng)態(tài)綁定,一般在運(yùn)行時(shí)刻才能確定方法的具體執(zhí)行對(duì)象。
實(shí)現(xiàn)多態(tài)的方式:
- 方法重寫(xiě)
- 方法重載
- 父類(lèi)引用指向子類(lèi)對(duì)象
舉例如下:
Teenagers tee = new Student();
以上就是父類(lèi)的引用指向子類(lèi)對(duì)象,指向了Teenager的子類(lèi)對(duì)象Student。
在student中重寫(xiě)eat方法:
class Student extends Teenagers {
private Map<String,Object> homework;
@Override
public void eat() {
System.out.println("peach");
}
public void study() {
}
}
調(diào)用
tee.eat();
將會(huì)打印出peach。即通過(guò)方法重寫(xiě)的方式實(shí)現(xiàn)了多態(tài)。
面向?qū)ο蟮脑O(shè)計(jì)原則
六大基本原則:
- 單一職責(zé)原則(Single-Responsibility Principle)
- 開(kāi)閉原則(Open-Closed Principle)
- 里氏替換原則(Liskov-Substitution Principle)
- 接口隔離原則(Interface-Segregation Principle)
- 依賴(lài)倒置原則(Dependency-Inversion Principle)
- 迪米特法則(Law of Demeter)
單一職責(zé)原則
- 基本概念:一個(gè)類(lèi)只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)。就一個(gè)類(lèi)而言,應(yīng)該只有一個(gè)引起它變化的原因。
- 優(yōu)點(diǎn):
- 低耦合性,影響范圍小
- 降低類(lèi)的復(fù)雜度,職責(zé)分明,提高了可讀性
- 變更引起的風(fēng)險(xiǎn)低,利于維護(hù)
舉例:
對(duì)于一部手機(jī)有打電話,發(fā)短信,觸摸控制等功能
定義接口
// 接口定義單一職責(zé)
interface Callable {
void call();
}
interface Touchable {
void touch();
}
interface Message {
void sendMessage();
}
// 接口實(shí)現(xiàn)單一職責(zé)
class StandardCall implements Callable {
@Override
public void call() {
System.out.println("我要打電話了~");
}
}
class StandardTouch implements Touchable {
@Override
public void touch() {
System.out.println("我要開(kāi)始觸摸操作了~");
}
}
class StandardMessage implements Message {
@Override
public void sendMessage() {
System.out.println("我要發(fā)短信了~");
}
}
(上述方式完全依照單一職責(zé)原則,但在實(shí)際應(yīng)用中,多選擇采用針對(duì)方法的單一職責(zé)原則)
產(chǎn)品應(yīng)用
class Phone implements Callable, Touchable, Message {
// 無(wú)需重新定義需要有的行為,直接用已有的
Callable callable = new StandardCall();
Touchable touchable = new StandardTouch();
Message message = new StandardMessage();
@Override
public void call() {
callable.call();
}
@Override
public void touch() {
touchable.touch();
}
@Override
public void sendMessage() {
message.sendMessage();
}
}
public class Demo {
public static void main(String[] args) {
Phone phone = new Phone();
phone.call();
phone.touch();
phone.sendMessage();
}
}
此時(shí)若我們的手機(jī)從電阻觸屏更換到了電容觸屏技術(shù),只需要換掉Touchable實(shí)現(xiàn)類(lèi)中的行為方法體,別的地方都不需要修改
class StandardTouch implements Touchable {
@Override
public void touch() {
System.out.println("我是新的電容觸摸,我要開(kāi)始觸摸操作了~");
}
}
開(kāi)閉原則
- 概念:一個(gè)軟件實(shí)體(軟件實(shí)體可以指一個(gè)軟件模塊、一個(gè)由多個(gè)類(lèi)組成的局部結(jié)構(gòu)、一個(gè)獨(dú)立的類(lèi)甚至一個(gè)函數(shù))應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。即軟件實(shí)體應(yīng)盡量在不修改原有代碼的情況下進(jìn)行擴(kuò)展。
- 優(yōu)點(diǎn):
- 提高系統(tǒng)的靈活性、可復(fù)用性和可維護(hù)性
同樣以手機(jī)為例,我們的手機(jī)擁有自己的屬性和行為,在線下進(jìn)行瘋狂的售賣(mài)中,此時(shí),雙十一來(lái)了,要展開(kāi)一波促銷(xiāo)活動(dòng),但促銷(xiāo)活動(dòng)是暫時(shí)的。
手機(jī)類(lèi)
// 手機(jī)類(lèi)
public class SamsungPhone {
private String model;
private String color;
private double price;
public SamsungPhone(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}
public String getModel() {
return model;
}
public String getColor() {
return color;
}
public double getPrice() {
return price;
}
}
//售賣(mài)
public class Demo {
public static void main(String[] args) {
SamsungPhone samsungPhone = new SamsungPhone("Galaxy S8","green",200);
System.out.println(samsungPhone.getColor() + "的" +samsungPhone.getModel() + "售價(jià)為:" + samsungPhone.getPrice() + "元");
}
}
雙十一來(lái)臨,開(kāi)閉原則擁抱變化,對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉
// 擴(kuò)展促銷(xiāo)手機(jī)類(lèi)
public class SamsungSale extends SamsungPhone{
public SamsungSale(String model, String color, double price) {
super(model, color, price);
}
public double getPrice() {
return super.getPrice() * 0.8;
}
}
里氏替換原則
- 概念:強(qiáng)調(diào)的是設(shè)計(jì)和實(shí)現(xiàn)要依賴(lài)于抽象而非具體;子類(lèi)只能去擴(kuò)展基類(lèi),而不是隱藏或者覆蓋基類(lèi)。即設(shè)計(jì)不要破壞繼承關(guān)系。
- 優(yōu)點(diǎn):
- 開(kāi)閉原則的體現(xiàn),約束繼承泛濫
- 提高系統(tǒng)的健壯性、擴(kuò)展性和兼容性
接口隔離原則
- 概念:接口中的方法應(yīng)該盡量少,不要使接口過(guò)于臃腫;接口盡量細(xì)化。
- 優(yōu)點(diǎn):
- 高內(nèi)聚、低耦合
- 可讀性高、易于維護(hù)
案例:
一水果店的進(jìn)貨出貨收銀系統(tǒng)
違背接口隔離原則(將所有方法都集中在一個(gè)接口類(lèi)中)
public interface FruitStoreInterface {
/**
* 計(jì)算價(jià)格
*/
public void method1();
/**
* 收銀
*/
public void method2();
/**
* 點(diǎn)貨
*/
public void method3();
/**
* 進(jìn)貨
*/
public void method4();
/**
* 出貨
*/
public void method5();
}
根據(jù)接口隔離原則修改后
// 進(jìn)貨
public interface StockPurchaseInterface {
/**
* 點(diǎn)貨
*/
public void method3();
/**
* 進(jìn)貨
*/
public void method4();
}
// 出貨
public interface OutPurchaseInterface {
/**
* 出貨
*/
public void method5();
}
// 收銀
public interface CalMoneyInterface {
/**
* 計(jì)算價(jià)格
*/
public void method1();
/**
* 收銀
*/
public void method2();
}
依賴(lài)倒置原則
- 概念:系統(tǒng)抽象化的具體實(shí)現(xiàn),要求面向接口編程
- 優(yōu)點(diǎn):
- 減少類(lèi)間的耦合性,提高系統(tǒng)的穩(wěn)定性
- 降低并行開(kāi)發(fā)引起的風(fēng)險(xiǎn)
- 提高代碼的可讀性和可維護(hù)性
案例:
學(xué)生讀書(shū)
違背依賴(lài)倒置原則設(shè)計(jì):
// 學(xué)生類(lèi)
public class Student {
public void doSomething(YuwenBook book){
book.readBook();
}
}
//書(shū)本類(lèi)語(yǔ)文
public class YuwenBook {
public void readBook(){
System.out.println("I am reading yuwen book!");
}
}
//調(diào)用
public class Demo {
public static void main(String[] args) {
Student student = new Student();
YuwenBook yuwenBook = new YuwenBook();
student.doSomething(yuwenBook);
}
}
若需求有變,我們不看語(yǔ)文書(shū)了,轉(zhuǎn)看數(shù)學(xué)書(shū),需要改動(dòng)的地方就多了。依照依賴(lài)倒置原則修改如下:
//書(shū)本統(tǒng)一接口類(lèi)
public interface Book {
public void readBook();
}
//學(xué)生類(lèi)
public class Student {
public void doSomething(Book book){
book.readBook();
}
}
// 語(yǔ)文書(shū)
public class YuwenBook implements Book{
public void readBook(){
System.out.println("I am reading yuwen book!");
}
}
//數(shù)學(xué)書(shū)
public class ShuxueBook implements Book {
public void readBook() {
System.out.println("I am reading shuxue book");
}
}
//調(diào)用
public class Demo {
public static void main(String[] args) {
Student student = new Student();
//讀語(yǔ)文書(shū)
YuwenBook yuwenBook = new YuwenBook();
student.doSomething(yuwenBook);
//讀數(shù)學(xué)書(shū)
ShuxueBook shuxueBook = new ShuxueBook();
student.doSomething(shuxueBook);
}
}
迪米特法則
- 概念:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解;降低系統(tǒng)的耦合度,使一個(gè)模塊的修改盡量少的影響其他模塊,擴(kuò)展會(huì)相對(duì)容易。
- 優(yōu)點(diǎn):
- 使軟件有更好的可維護(hù)性和適應(yīng)性
- 對(duì)象較少依賴(lài)其他對(duì)象的內(nèi)壁結(jié)構(gòu),可以改變對(duì)象容器而不用改變他的調(diào)用者
案例:
朋友A問(wèn)朋友B,朋友C在干嘛,此時(shí)B也不知道,于是,B打電話給C詢(xún)問(wèn)
違背迪米特法則
public class FriendA {
public String askB(FriendB b) {
b.call();
b.sayHello();
b.askWhere();
return b.askWhatDo();
}
}
public class FriendB {
public void call() {
}
public void sayHello() {
}
public void askWhere() {
}
public String askWhatDo() {
return "跳繩";
}
}
根據(jù)迪米特法則,A只想知道C在干嘛,而不用知道B是通過(guò)什么手段或者方式得知C的行為,修改后:
public class FriendA {
public String askB(FriendB b) {
return b.call();
}
}
public class FriendB {
public String call() {
sayHello();
askWhere();
return askWhatDo();
}
private void sayHello() {
}
private void askWhere() {
}
private String askWhatDo() {
return "跳繩";
}
}
結(jié)論:面向?qū)ο蟮脑O(shè)計(jì)原則都是為了擁抱變化而研究出來(lái)的一系列捷徑