溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

面向?qū)ο?個特性7個原則6種關(guān)系是什么

發(fā)布時間:2021-10-13 10:41:45 來源:億速云 閱讀:112 作者:iii 欄目:編程語言

這篇文章主要介紹“面向?qū)ο?個特性7個原則6種關(guān)系是什么”,在日常操作中,相信很多人在面向?qū)ο?個特性7個原則6種關(guān)系是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”面向?qū)ο?個特性7個原則6種關(guān)系是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

  1. 依照PHP的語法為主,不同的編程語言,有不同的方式,但大體上都是一樣的。

  2. 面向?qū)ο蟮乃枷朐谟诶斫夂褪褂谩?/p>

  3. 文章所說的接口,都是編程語言語法的接口(interface),而不是前端調(diào)用的接口(api)。

為什么會有這么多的概念?知其所以然。

軟件,是為了解決人類發(fā)展的問題,方便人類的工具,如果一個計算機,或者一個軟件只會算數(shù),那么遇見匯率換算怎么辦?是不是可以說計算機本身如果沒有太多的固有功能,就無法完成某些事。而現(xiàn)在的軟件,可以幫助人們購物,相親,娛樂。這么復(fù)雜的功能來說,如果軟件思想沒有發(fā)展出更高級的思想,它是無法為人類服務(wù)的,所以為了可維護性更強,具有更強的功能,必須在計算機軟件編程本身上提出一些更高級的概念,用于實現(xiàn)比算加減乘除更復(fù)雜的功能,多樣化的規(guī)則成了一套實用高效的規(guī)范,那么就是下文看到的各種計算機名詞。

面向?qū)ο?/h3>

面向

“面向”此處可以理解為按照什么思路去編程。

對象

對象是一種依照事物為中心的編程思想,萬物皆對象,由實體引發(fā)事件,對象是真實存在的,對象也可以理解為是把數(shù)據(jù)結(jié)構(gòu)和處理它們的方法,組成對象。達到了軟件工程的三個目標(biāo),重用性靈活性和擴展性。 重用性: 一個類里面的方法可以多次使用。 靈活性: 可以表現(xiàn)為多態(tài),可重復(fù)調(diào)動等特點,自由度很高,條條大路通羅馬。 擴展性: 多態(tài),繼承都有這個特性,可便于多樣化擴展,進行抽離,降低耦合。

可以理解為對象的抽象化概念,分離出相同的特點,并加以歸類。 把相同行為的對象歸納為類,一個人是一個對象,但是多個人可以歸納為一個人類,人類指的不是某一個,而是一個虛擬的實體概念。為什么有人這個類?因為人有雙手,會用火,有文明,學(xué)習(xí)能力強等因素,如果想要從人類上說某個人,那就是舉一個實例,也就是實例化。

成員屬性

屬性可以理解數(shù)據(jù),數(shù)據(jù)是信息和表現(xiàn)形式的載體。依照人為例,人有鼻子有眼,這個就是人的屬性??梢杂? 來形容。

成員方法

方法可以理解為函數(shù)。方法是控制數(shù)據(jù)的管家。依照人為例,人會說話,會吃飯,這就人的方法??梢杂? 來形容。

接口

可以理解為一個類中需要指定它需要做什么,但是不需要去做,起到一個規(guī)范示例的作用,就是一個標(biāo)準(zhǔn),需要其它的類去實現(xiàn)它。例如定義了usb接口的尺寸,大小,數(shù)據(jù)線連接方法,可以類比成一個接口規(guī)范,全世界的usb接口都通用,無論是U盤,充電器線,鼠標(biāo),鍵盤。這些實例都可以根據(jù)這個約束規(guī)范,去制造東西。接口的使用需要用 實現(xiàn) 兩個字形容。

類的三個特性

封裝: 通過封裝隱藏類的內(nèi)部方法或者數(shù)據(jù),只允許訪問可以訪問的資源,保證安全性。擬人化來說,就是姓名是公開的,銀行密碼的信息是個人的,PHP可用public protected private去修飾。

繼承: 繼承使類得到泛化,兒子繼承爸爸,可以獲得父級或者父級往上的非私有屬性,或者方法,使用extends關(guān)鍵字。

多態(tài): 可實現(xiàn)基于對象類型的動態(tài)分派,不同的人做同一件事,得到不同的結(jié)果。相親這件事:女生遇到流氓會說滾,遇到帥哥會說么么噠。

面向?qū)ο髨鼍跋戮幊?個原則,宗旨:面向接口編程,針對目標(biāo)。精簡代碼,降低耦合。靈活分離,減少影響。抽離相同的代碼,便于復(fù)用維護。

單一原則: 一個類就做一件事,職責(zé)被完整的封裝在一個類中。不會引起混亂,提高重用性,低耦合的設(shè)計可以降低軟件開發(fā)后期的維護。

開閉原則: 對修改關(guān)閉,對擴展開放。因為需求變更,運行環(huán)境升級等原因需要改代碼,如果沒有出現(xiàn)bug,那么不推薦改原來的代碼,可以在原基礎(chǔ)上進行擴充。既增加了擴展性,又保證原來的邏輯不出問題。所謂的“祖?zhèn)鞔a,勿動”,也就是這么一回事。

里氏代換原則: 通俗講:所有能用到老爸的地方,兒子也能使用。軟件中能夠使用的基類對象,那么就要做到任何地方能使用子類對象而不受影響。也就是子類能夠替換程序中父類出現(xiàn)的任何地方,并保證邏輯不變和正確,這里面暗含著不推薦重寫父類的意思。正是因為有了這個標(biāo)準(zhǔn),才能防止父級一旦修改,就會殃及子級發(fā)生故障的情況。這個原則實現(xiàn)了開閉原則的形式,子類就相當(dāng)于擴展。實質(zhì)上這個原則是要告訴我們,繼承需要注意的問題和遵循的原則。但繼承是增加了父子類的耦合關(guān)系,為了解決依賴,可以適當(dāng)通過聚合,組合,依賴等來解決。

依賴倒轉(zhuǎn)原則: 就是面向接口編程。把共用的可復(fù)用的方法放置到抽象類,抽象思維編程,或者接口當(dāng)中,依照抽象耦合的方式是原則的關(guān)鍵,目的是降低耦合。高層模塊(舉個例子:高層模塊就是框架底層的代碼,依照PHP為例,框架底層的代碼,好多都是抽象類或者接口)不依賴底層模塊,二者依賴于抽象。抽象不應(yīng)該依賴細節(jié),細節(jié)應(yīng)該依賴抽象,也就是做到細節(jié)和非細節(jié)的分離,相對于細節(jié)的多變性,抽象的東西要穩(wěn)定的多。抽象為基礎(chǔ)搭建的架構(gòu)比細節(jié)為基礎(chǔ)的架構(gòu)要穩(wěn)定的多。舉個例子,功能的大體實現(xiàn)可以使用抽象類,但是細節(jié),可以使用具體的類去實現(xiàn)。這里所謂的抽象,是用于定制規(guī)范和整體架構(gòu)。 舉個栗子:

//這段代碼適用于發(fā)送郵件,但是要增加發(fā)送微信的功能,是不是就顯得麻煩了?這里不要抬杠說把“Email $email”去掉,如果項目中大量的業(yè)務(wù)邏輯已經(jīng)這樣寫了,把“Email $email”去掉,可能要出問題的。
<?php
class Email {
   public function send() {
        return '發(fā)送電子郵件';
   }
}

class WeChat {
	public function send() {
        return '發(fā)送微信消息';
   }
}

class Person {
	public function receive(Email $email) {
		return $email->send();
	}
}
$person = new Person();
echo $person->receive(new Email());

再看看 優(yōu)化的結(jié)果,所謂的抽象就是發(fā)送信息,細節(jié)就是發(fā)送信息的方式和內(nèi)容,抽象和細節(jié)做了分離,降低耦合。

<?php

//接口定義大致的方法,大方向
interface SendMsg {
	public function send();
}

//具體的類去實現(xiàn)細節(jié)
class Email implements SendMsg {
   public function send() {
        return '發(fā)送電子郵件';
   }
}

//具體的類去實現(xiàn)細節(jié)
class WeChat implements SendMsg {
	public function send() {
        return '發(fā)送微信消息';
   }
}

//此處降低耦合
class Person {
	public function receive(SendMsg $send_msg) {
		return $send_msg->send();
	}
}


$person = new Person();
//靈活調(diào)用
echo $person->receive(new Email());
echo $person->receive(new WeChat());

接口隔離原則: 還是為了降低耦合,減少接口類中臃腫的代碼段,一個類對另一個類的依賴應(yīng)該建立在最小的接口上,通俗的講就是需要什么就提供什么,不需要的就不要提供。比如接口類Test一共有func1,func2,func3,func4,func5 5個方法,A類依賴Test接口 func1,func2,func3三個方法,B類依賴Test接口 func1,func2,func4三個方法。這樣的接口func5就沒有用上,應(yīng)該做接口拆分,拆分成A類和B類依賴的接口僅僅夠用程度的接口即可,并且增加安全性,這里的拆,就是具有隔離不需要的代碼的作用。

<?php
//接口定義了5個方法
interface TestInterface {
	public function func1();
	public function func2();
	public function func3();
	public function func4();
	public function func5();
}

//A類依賴了接口中123三個方法,但func4 和 func5用不上
class A implements TestInterface {
	public function func1() { return '實現(xiàn)了TestInterface接口的func1方法';}
	public function func2() { return '實現(xiàn)了TestInterface接口的func2方法';}
	public function func3() { return '實現(xiàn)了TestInterface接口的func3方法';}
	public function func4() { return '這兩個方法用不上,但是由于PHP語法問題,需要去實現(xiàn)';}
	public function func5() { return '這兩個方法用不上,但是由于PHP語法問題,需要去實現(xiàn)';}
}


//A類依賴了接口中124三個方法,但func3 和 func5用不上
class B implements TestInterface {
   public function func1() { return '實現(xiàn)了TestInterface接口的func1方法';}
   public function func2() { return '實現(xiàn)了TestInterface接口的func2方法';}
   public function func3() { return '這兩個方法用不上,但是由于PHP語法問題,需要去實現(xiàn)';}
   public function func4() { return '實現(xiàn)了TestInterface接口的func4方法';}
   public function func5() { return '這兩個方法用不上,但是由于PHP語法問題,需要去實現(xiàn)';}
}

再看不臃腫的代碼:

<?php
interface TestInterface_A {
	public function func1();
	public function func2();
	public function func3();
}

interface TestInterface_B {
    public function func1();
    public function func2();
    public function func4();
}

//A類實現(xiàn)了接口中123三個方法,無需依賴額外的方法
class A implements TestInterface_A {
	public function func1() { return '實現(xiàn)了TestInterface接口的func1方法';}
	public function func2() { return '實現(xiàn)了TestInterface接口的func2方法';}
	public function func3() { return '實現(xiàn)了TestInterface接口的func3方法';}
}


//A類實現(xiàn)了接口中124三個方法,無需依賴額外的方法
class B implements TestInterface_B {
    public function func1() { return '實現(xiàn)了TestInterface接口的func1方法';}
    public function func2() { return '實現(xiàn)了TestInterface接口的func2方法';}
    public function func4() { return '實現(xiàn)了TestInterface接口的func4方法';}
}

合成復(fù)用原則: 多用組合(has-a),少用繼承(is-a),可以降低類與類之間的耦合程度。遇見額外增加的功能,需要擴展,通過關(guān)聯(lián),而不是繼承。因為使用繼承,后期改父級代碼可能會株連子級,引起錯誤。 繼承復(fù)用又稱之為白箱復(fù)用,組合聚合使用稱之為黑箱復(fù)用。

迪米特法則/最少知道原則 一個軟件實體盡可能少的與其它實體發(fā)生作用,限制了編程中通信的寬度和深度,不管依賴的類有多么的復(fù)雜,都盡量把邏輯封裝到類內(nèi)部,除了對外提供public的方法,不對外泄露任何無關(guān)信息。只和朋友通信,朋友通常是當(dāng)前類、當(dāng)前對象、成員屬性,成員方法參數(shù),成員方法返回值這些。其余的都是陌生人,不可直接調(diào)用。 法則又可以分為狹義法則和廣義法則。狹義的說法是:類A和類B發(fā)生關(guān)聯(lián),類B和類C發(fā)生關(guān)聯(lián),那么類A和類C是不能直接訪問的,需要通過B。優(yōu)點是降低耦合,缺點是需要大量的局部化設(shè)計,讓類A可以訪問類C,造成模塊間使用效率降低。廣義的說法是:盡量創(chuàng)建松耦合的類,控制信息的過載,類之間的耦合度越低,越有利于復(fù)用,但是需要更高的抽象分離思想。

并由此出現(xiàn)了23種設(shè)計模式,設(shè)計模式用于解決經(jīng)典場景下的經(jīng)典問題而出來的通用實用規(guī)范。但23種有些并不適用于PHP語言,一旦強制使用,就缺失了弱類型語言的優(yōu)點。

擴展

面向過程

面向過程是依事件為中心,分析出解決問題的步驟,將代碼分成若干個過程/函數(shù),一步步實現(xiàn),其中,函數(shù)或過程是最小的模塊封裝單位,然后調(diào)用這些函數(shù),可以稱之為方法。所謂的通俗講封裝就是把一堆代碼括起來。 面向?qū)ο笠彩腔诿嫦蜻^程的思想,面向?qū)ο髮崿F(xiàn),也必定有相應(yīng)的過程,所以有很多相同點。

過程與函數(shù)的區(qū)別

過程: 無返回值。 函數(shù): 有返回值。

類之間的6種關(guān)系:繼承、依賴、關(guān)聯(lián)、聚合、組合、泛化、實現(xiàn)

繼承: 兒子繼承爸爸,子類可以使用父類的任何非私有成員方法或成員屬性,且可以隨意擴展,并且可以通過子類重寫放寬對資源的訪問修飾,且可以重寫父類非私有的的方法或成員屬性。很好理解,不多解釋。

依賴: 假設(shè)有兩個類:A和B,類B的某個成員方法的參數(shù)有類A,則類B依賴類A (也就是常說的uses-a,這里應(yīng)該是uses-b)。

<?php
class A {
    public function one() {
        return 'one';
    }
}
class B {
    public function two(A $a) {
        return $a->one();
    }
}
$b_obj = new B();
echo $b_obj->two(new A());

關(guān)聯(lián): 強依賴關(guān)系,當(dāng)所依賴的類已經(jīng)成為了類成員的時候,此時會被加載到內(nèi)存當(dāng)中的,而不是參數(shù)的時候(如果是單純的依賴,那么依賴所在的方法如果不調(diào)用,就不會發(fā)生什么),關(guān)聯(lián)有一對多,多對多之分,也有單向雙向之分,比如單向一對多。

<?php
class A {
    public function one() {
        return 'one';
    }
}
class B {
    public $obj_a;
    public function two() {
        $this->obj_a = new A();
        return $this->obj_a->one();
    }
}
$b_obj = new B();
print_r($b_obj->two());

聚合: A和B的關(guān)系是整體和局部的關(guān)系(has-a),整體和局部是可以分開的。DemoDateTime包含了DemoDate和DemoTime,也就是DemoDateTime聚合了DemoDate和DemoTime。

<?php
class DemoDate {
    public function getDate() {
        return date("Y/m/d");
    }
}
class DemoTime {
    public function getTime() {
        return date("H:i:s");
    }
}

class DemoDateTime {
    public function getDateTime() {
        $date_obj = new DemoDate();
        $time_obj = new DemoTime();
        $datetime = $date_obj->getDate() . ' ' . $time_obj->getTime();
        return $datetime;
    }
}
$datetime_obj = new DemoDateTime();
echo $datetime_obj->getDateTime();

組合: 組合關(guān)系也是整體和部分的關(guān)系,但它是強聚合關(guān)系??梢岳斫鉃楦鱾€部分不能離開整體,離開了就要出問題。

泛化

就是繼承。

實現(xiàn)

實現(xiàn)就是一個抽象類被其它類實現(xiàn)。

面向接口編程

通俗講就是多用用接口,把接口作為定義大骨架,來使用,剩下的細節(jié),交給實現(xiàn)接口的類去使用,也就是將定義與實現(xiàn)分離,需要開發(fā)者擁有分離的抽象思想。

什么時候使用抽象類什么時候使用接口?

(以上內(nèi)容為原創(chuàng),以下內(nèi)容全部來源于網(wǎng)絡(luò),然后進行整合,感謝各位網(wǎng)友的回復(fù)。) 接口應(yīng)有兩類:第一類是對一個體的抽象,它可對應(yīng)為一個抽象體(abstract class);第二類是對一個體某一方面的抽象,即形成一個抽象面(interface),一個體有可能有多個抽象面。   操作數(shù)據(jù)庫就必須會用到 Insert Update Select ,所以Insert Update Select 做成接口 但是,每個功能操作的內(nèi)容又不一樣,所以,做一個抽象類繼承接口然后抽象類的派生類去實現(xiàn)抽象類的具體方法。

接口是一組規(guī)則的集合,它規(guī)定了實現(xiàn)本接口的類或接口必須擁有的一組規(guī)則 抽象類和接口的區(qū)別在于使用動機。使用抽象類是為了代碼的復(fù)用,而使用接口的動機是為了實現(xiàn)多態(tài)性。

如果這個概念在我們腦子中是確確實實存在的,就用抽象類。 否則的話,如果這個概念僅僅是一方面的特性,比如會飛的,能跑的,這些我們就設(shè)置為接口。 兩個概念模糊,不知道設(shè)置為抽象類還是接口的時候,一般我們設(shè)置為接口,原因是我們實現(xiàn)了這個接口還可以繼承。

抽象類適合用來定義某個領(lǐng)域的固有屬性,也就是本質(zhì),接口適合用來定義某個領(lǐng)域的擴展功能。 當(dāng)需要為一些類提供公共的實現(xiàn)代碼時,應(yīng)優(yōu)先考慮抽象類。因為抽象類中的非抽象方法可以被子類繼承下來,使實現(xiàn)功能的代碼更簡單。 當(dāng)注重代碼的擴展性跟可維護性時,應(yīng)當(dāng)優(yōu)先采用接口。①接口與實現(xiàn)它的類之間可以不存在任何層次關(guān)系,接口可以實現(xiàn)毫不相關(guān)類的相同行為,比抽象類的使用更加方便靈活;②接口只關(guān)心對象之間的交互的方法,而不關(guān)心對象所對應(yīng)的具體類。接口是程序之間的一個協(xié)議,比抽象類的使用更安全、清晰。一般使用接口的情況更多。

當(dāng)描述一組方法的時候使用接口 當(dāng)描述一個虛擬的物體的時候使用抽象類

抽象類是跟繼承類是“is”的關(guān)系,接口和實現(xiàn)類是"like"的關(guān)系,從這個角度出發(fā),應(yīng)該可以看出很多東西。其它的區(qū)別只是一些語法,用法規(guī)范上的區(qū)別,核心思想就是這個is-like區(qū)別。

到此,關(guān)于“面向?qū)ο?個特性7個原則6種關(guān)系是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)
AI