设计模式之 六大原则
一.單一職責
定義:?一個類承擔的職責不宜過多,或者說就一個類而言,應該僅有一個引起它變化的原因
如果一個類的職責承擔過多,如果涉及到其中每一個職責變動的時候,都要修改這個類,而且在我們要復用這個類中的其中一個職責的時候也沒法做到復用。
class Act{public function run(){$data = $this->curl($url);}public function curl($url, $data = array(), $timeout = 5) {$ch = curl_init();if (!empty($data) && $data) {if(is_array($data)){$formdata = http_build_query($data);} else {$formdata = $data;}curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, $formdata);}curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);curl_setopt($ch, CURLOPT_ENCODING, '');$result = curl_exec($ch);curl_close($ch);return $result;} }看到項目里經常有把請求第三方接口的curl方法寫在當前類里,比如上面的活動類Act耦合了curl方法,如果此時又有另外一個類要使用curl方法,這個類并不需要活動類的其它功能此時就不能復用Act的curl方法
只能在這個類里在增加一個curl方法,如此下去,隨著類越來越多,項目里到處是curl方法,假如某一天需要把超時改成10秒,那就慘了,得一個個類里去修改。其實我們完全可以把curl方法放到curl類里,將Act類和curl解耦,
這樣項目統(tǒng)一使用curl類的curl方法,新增功能的時候可復用Curl的curl方法,修改的時候只需修改Curl類。
?
二.開放封閉原則
定義: 軟件實體(類,函數模塊) 應該是可以擴展的,但是不可以修改
這應該是軟件開發(fā)的理想境界,其實我們不可能做到完全對修改關閉,只是盡量做到即可。
比如游戲里的支付回調,可以抽象為3個步驟,驗證第三方參數,發(fā)道具給玩家,返回報文給第三方。
?
上面是一個第三方回調的主體代碼,我抽掉了其他的業(yè)務邏輯,每個支付子類繼承子一個抽象父類,這樣做的好處是可以把公共的邏輯放到父類里,無需每個子類重復寫公共邏輯,假如要新增支付寶,
只需要新增一個支付寶類,然后實現子類特有的業(yè)務邏輯即可。當然如果某天要新增文件日志,那必須改父類了,團隊里開發(fā)人員水平參差不齊,我們可以把 Notify父類這個文件設置為指定人員可改。
這樣基本做到了對擴展開防,對修改關閉。
三.里氏替換原則
定義:?子類型必須能夠替換掉他們的父類型
意思是盡量不要重寫父類的方法,因為父類的方法一般是公用的
由于世界上最好的語言是弱類型,這個原則PHP實在無法理解,這里使用java來理解這個原則
class Car{String carType;public Car(String carType){this.carType = carType;} public void run(){System.out.println(carType + "跑");} }class HondaCar extends Car{public HondaCar(String carType){super(carType);} /* public void run(){throw new Exception();}*/ }class FordCar extends Car{public FordCar(String carType){super(carType);} }public class Client {public static void main(String[]agrs){Car h = new HondaCar("豐田"); h.run();FordCar f = new FordCar("福特");f.run(); } }子類型FordCar f對象,可以替換掉父類型Car h對象,但假如 HondaCar類重寫父類的run方法,顯然替換會造成程序異常。
然而有的時候我們不得不重寫父類的方法,只要重寫父類方法能給我們帶來大利大于弊的時候即可。
?
四.依賴倒轉原則?
定義 : 抽象不應該依賴于細節(jié),細節(jié)應該依賴于抽象,要針對接口編程而不是對具體實現編程
這個原則還是用java來理解
class Members{public void set(){Redis redis = new Redis();redis.set("u_key", "u_value");} }class Redis{public void set(String key, String val){System.out.println("Redis設置key:" + key + "value :" + val + "成功!");} }public class Client {public static void main(String[]agrs){Members m = new Members();m.set();} }假如存貯換為Mysql那么我們得修改Members類,我們改下代碼,增加一個Istore接口,Redis和Mysql類實現set方法。具體的類名我們可以寫到配置文件里,然后通過反射實例化相應的對象,
換存貯只需要修改配置文件,增加對應的存儲類即可做到符合開閉原則。
?
五.迪米特法則?
定義 : 一個類應該盡量降低自己成員的訪問權限,如果兩個類不必發(fā)生直接通訊,那么這兩個類就不應該直接發(fā)生相互作用,如果其中一個類要調用另外一個類的方法,可以通過第三者轉發(fā)這個調用
這個原則強調盡量降低類和類之間的耦合度,一個處于松耦合的類一旦被修改,不會對關聯的類造成太大的影響
class Cache{function getResult(){return array('id'=>1, 'name'=>'PHP');} }class Mysql{function getResult(){return array('id'=>1, 'name'=>'PHP');} }class Client{public static function main(){$data = array();$cache = new Cache();if(!$data = $cache->getResult()){$db = new Mysql();$data = $db->getResult();}print_r($data);} } Client::main();上面這個是我們經常碰到的業(yè)務場景,先從cache里取數據,取不到就從db里取,萬一要加個文件里取,就得修改客戶端配置,如果調用的地方很多,每個地方都得改。
此時根據迪米特法則完全可以引入一個對象當中間人,使得客戶端不用直接和db,cache交互。
?
六.接口隔離原則?
定義 :?不要建立龐大臃腫的接口,接口中的方法盡量少
?如果違反這一原則,有時候不需要這些方法子類也不得不實現這個方法。
?下面以高考作為一個栗子(純屬虛構), 最初教育部規(guī)定各省市考試有7科,部分文理,這樣造成喜歡文科的也不得不考理科,喜歡理科的不得不考文科,上海表示抗議,要分文理科,于是上海私自做決定, 考試我還是考(實現全國卷統(tǒng)一接口),但是文科生理綜不計入總分(空方法實現),理科生分科不計入總分(空方法實現),?接著北京,天津等直轄市紛紛效仿,深圳廣州等城市還是按照綜合考試,覺得這樣有利于學生綜合能力發(fā)展,這時候教育部想了個辦法把學科分成主課+文+理(三個接口,這樣做到了接口最小化), 愿意分文理就靠文科的,愿意綜合的就靠所有的,這樣大家都沒意見了。
?
如果某些時候遵守規(guī)則讓你開發(fā)效率更低,那還不如違反規(guī)則以得到更好的開發(fā)效率,規(guī)則是死的,人是活的,我們開發(fā)的時候盡量遵守這些規(guī)則即可
?
?
轉載于:https://www.cnblogs.com/gaoqin31/p/7608243.html
總結
以上是生活随笔為你收集整理的设计模式之 六大原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构-编程实现一个双链表的建立,双链
- 下一篇: 设计模式(十)——抽象工厂模式