av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

面向?qū)ο笾叽蠡驹瓌t(JavaScript)

面向?qū)ο缶幊逃凶约旱奶匦耘c原則,如果對(duì)于面向?qū)ο笥幸恍┝私獾脑?huà),面向?qū)ο笕筇卣?,封裝、繼承、多態(tài),如果對(duì)面向?qū)@三個(gè)概念不太了解,請(qǐng)參考面向?qū)ο笾齻€(gè)基本特征(JavaScript)

成都創(chuàng)新互聯(lián)是專(zhuān)業(yè)的臨朐網(wǎng)站建設(shè)公司,臨朐接單;提供成都做網(wǎng)站、成都網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行臨朐網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

單一職責(zé)

如果我們?cè)诰帉?xiě)程序的時(shí)候,一類(lèi)或者一個(gè)方法里面包含了太多方法,對(duì)于代碼的可讀性來(lái)說(shuō),無(wú)非是一場(chǎng)災(zāi)難,對(duì)于我們來(lái)說(shuō)。所以為了解決這個(gè)問(wèn)題,出現(xiàn)了單一職責(zé)。

什么是單一職責(zé)

單一職責(zé):又稱(chēng)單一功能原則,面向?qū)ο笪鍌€(gè)基本原則(SOLID)之一。它規(guī)定一個(gè)類(lèi)應(yīng)該只有一個(gè)發(fā)生變化的原因。(節(jié)選自百度百科)

按照上面說(shuō)的,就是對(duì)一個(gè)類(lèi)而言,應(yīng)該僅有一個(gè)引起它變化的原因。換句話(huà)說(shuō),一個(gè)類(lèi)的功能要單一,只做與它相關(guān)的事情。在類(lèi)的設(shè)計(jì)過(guò)程中要按職責(zé)進(jìn)行設(shè)計(jì),彼此保持正交,互不干涉。

單一職責(zé)的好處

  1. 類(lèi)的復(fù)雜性降低,實(shí)現(xiàn)什么職責(zé)都有清晰明確的定義
  2. 可讀性提高,復(fù)雜性降低,那當(dāng)然可讀性提高了
  3. 可維護(hù)性提高,可讀性提高,那當(dāng)然更容易維護(hù)了
  4. 變更引起的風(fēng)險(xiǎn)降低,變更是必不可少的,如果接口的單一職責(zé)做得好,一個(gè)接口修改只對(duì)相應(yīng)的實(shí)現(xiàn)類(lèi)有影響,對(duì)其他的接口無(wú)影響,這對(duì)系統(tǒng)的擴(kuò)展性、維護(hù)性都有非常大的幫助。

實(shí)例

 
 
 
 
  1. class ShoppinCar {
  2.     constructor(){
  3.         this.goods = [];
  4.     }
  5.     addGoods(good){
  6.         this.goods = [good];
  7.     }
  8.     getGoodsList(){
  9.         return this.goods;
  10.     }
  11. }
  12. class Settlement {
  13.     constructor(){
  14.         this.result = 0; 
  15.     }
  16.     calculatePrice(list,key){
  17.         let allPrice = 0;
  18.         list.forEach((el) => {
  19.             allPrice += el[key];
  20.         })
  21.         this.result = allPrice;
  22.     }
  23.     getAllPrice(){
  24.         return this.result;
  25.     }
  26. }

用上面的代碼來(lái)說(shuō)ShoppinCar類(lèi)存在兩個(gè)方法addGoods和getGoodsList,分別是添加商品和獲取商品列表。Settlement類(lèi)中存在兩個(gè)方法calculatePrice和getAllPrice分別做的事情是計(jì)算價(jià)錢(qián)與獲取總價(jià)錢(qián)。ShoppinCar與Settlement都是在做自己的事情。添加商品與計(jì)算價(jià)格,雖然在業(yè)務(wù)上是相互依賴(lài)的,但是在代碼中分別用兩個(gè)類(lèi),然他們自己做自己的事情。其中任何一個(gè)類(lèi)更改不會(huì)對(duì)另一個(gè)類(lèi)進(jìn)行更改。

開(kāi)閉原則

在一個(gè)類(lèi)中暴露出去的方法,若這個(gè)方法變更了,則會(huì)產(chǎn)生很大的后果,可能導(dǎo)致其他依賴(lài)于這個(gè)方法且有不需要變更的業(yè)務(wù)造成大面積癱瘓。為了解決這個(gè)問(wèn)題,可以單獨(dú)再寫(xiě)一個(gè)方法,若這個(gè)方法與這個(gè)類(lèi)中的其他方法相互依賴(lài)。

解決辦法:

  1. 把其中依賴(lài)的代碼copy一份到新的類(lèi)中。
  2. 在新類(lèi)中引用舊類(lèi)中的方法。

兩種方法都不是最好的解決方案。

第一種方法會(huì)導(dǎo)致代碼大量的重復(fù),第二種方法會(huì)導(dǎo)致類(lèi)與類(lèi)之間互相依賴(lài)。

什么是開(kāi)閉原則

開(kāi)閉原則:“軟件中的對(duì)象(類(lèi),模塊,函數(shù)等等)應(yīng)該對(duì)于擴(kuò)展是開(kāi)放的,但是對(duì)于修改是封閉的”,這意味著一個(gè)實(shí)體是允許在不改變它的源代碼的前提下變更它的行為。(節(jié)選自百度百科)

開(kāi)閉原則對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉,并不意味著不做任何修改,底層模塊的變更,必然要有高層模塊進(jìn)行耦合,否則就是一個(gè)孤立無(wú)意義的代碼片段。開(kāi)閉原則是一個(gè)最基本的原則,另外六個(gè)原則都是開(kāi)閉原則的具體形態(tài),是指導(dǎo)設(shè)計(jì)的工具和方法,而開(kāi)閉原則才是精神領(lǐng)袖.

開(kāi)閉原則好處

  1. 開(kāi)閉原則有利于進(jìn)行單元測(cè)試
  2. 開(kāi)閉原則可以提高復(fù)用性
  3. 開(kāi)閉原則可以提高可維護(hù)性
  4. 面向?qū)ο箝_(kāi)發(fā)的要求

實(shí)例

 
 
 
 
  1. class Drag {
  2.     down(){
  3.         //  ...
  4.     }   
  5.     move(){
  6.         //  ...
  7.         // 對(duì)拖拽沒(méi)有做任何限制可以隨意拖拽
  8.     }   
  9.     up(){
  10.         //  ...
  11.     }  
  12. }
  13. class LimitDrag extends Drag {
  14.     move(){
  15.         //  ...
  16.         //  重寫(xiě)該方法對(duì)拖拽進(jìn)行限制處理
  17.     }
  18. }

在LimitDrag中重寫(xiě)了move方法,若修改了可以滿(mǎn)足兩種需求,一種是限制型拖拽,一種是不限制型拖拽,任何一個(gè)更改了另外一個(gè)還是可以正常運(yùn)行。

里氏替換

每個(gè)開(kāi)發(fā)人員在使用別人的組件時(shí),只需知道組件的對(duì)外裸露的接口,那就是它全部行為的集合,至于內(nèi)部到底是怎么實(shí)現(xiàn)的,無(wú)法知道,也無(wú)須知道。所以,對(duì)于使用者而言,它只能通過(guò)接口實(shí)現(xiàn)自己的預(yù)期,如果組件接口提供的行為與使用者的預(yù)期不符,錯(cuò)誤便產(chǎn)生了。里氏替換原則就是在設(shè)計(jì)時(shí)避免出現(xiàn)派生類(lèi)與基類(lèi)不一致的行為。

什么是里氏替換

里氏替換原則:OCP作為OO的高層原則,主張使用“抽象(Abstraction)”和“多態(tài)(Polymorphism)”將設(shè)計(jì)中的靜態(tài)結(jié)構(gòu)改為動(dòng)態(tài)結(jié)構(gòu),維持設(shè)計(jì)的封閉性。“抽象”是語(yǔ)言提供的功能?!岸鄳B(tài)”由繼承語(yǔ)義實(shí)現(xiàn)。(節(jié)選自百度百科)

里氏替換好處

  1. 代碼共享,減少創(chuàng)建類(lèi)的工作量,每個(gè)子類(lèi)都擁有父類(lèi)的方法和屬性
  2. 提高代碼的重用性
  3. 子類(lèi)可以形似父類(lèi),但是又異于父類(lèi)。
  4. 提高代碼的可擴(kuò)展性,實(shí)現(xiàn)父類(lèi)的方法就可以了。許多開(kāi)源框架的擴(kuò)展接口都是通過(guò)繼承父類(lèi)來(lái)完成。
  5. 提高產(chǎn)品或項(xiàng)目的開(kāi)放性

實(shí)例

 
 
 
 
  1. //  抽象槍類(lèi)
  2. class AbstractGun {
  3.     shoot(){
  4.         throw "Abstract methods cannot be called";
  5.     }
  6. }
  7. //  步槍
  8. class Rifle extends AbstractGun {
  9.     shoot(){
  10.         console.log("步槍射擊...");
  11.     }
  12. }
  13. //  狙擊槍
  14. class AUG extends Rifle {
  15.     zoomOut(){
  16.         console.log("通過(guò)放大鏡觀察");
  17.     }
  18.     shoot(){
  19.         console.log("AUG射擊...");
  20.     }
  21. }
  22. //  士兵
  23. class Soldier {
  24.     constructor(){
  25.         this.gun = null;
  26.     }
  27.     setGun(gun){
  28.         this.gun = gun;
  29.     }
  30.     killEnemy(){
  31.         if(!this.gun){
  32.             throw "需要給我一把槍";
  33.             return;
  34.         }
  35.         console.log("士兵開(kāi)始射擊...");
  36.         this.gun.shoot();
  37.     }
  38. }
  39. //  狙擊手
  40. class Snipper extends Soldier {
  41.     killEnemy(aug){
  42.         if(!this.gun){
  43.             throw "需要給我一把槍";
  44.             return;
  45.         }
  46.         this.gun.zoomOut();
  47.         this.gun.shoot();
  48.     }
  49. }
  50. let soldier = new Soldier();
  51. soldier.setGun(new Rifle());
  52. soldier.killEnemy();
  53. let snipper = new Snipper();
  54. //  分配狙擊槍
  55. snipper.setGun(new AUG());
  56. snipper.killEnemy();
  57. snipper.setGun(new Rifle());
  58. // snipper.killEnemy();  //  this.gun.zoomOut is not a function

從上述代碼中可以看出,子類(lèi)和父類(lèi)之間關(guān)系,子類(lèi)方法一定是等于或大于父類(lèi)的方法。子類(lèi)能夠出現(xiàn)的父類(lèi)不一定能出現(xiàn),但是父類(lèi)出現(xiàn)的地方子類(lèi)一定能夠出現(xiàn)。

依賴(lài)倒置

如果方法與方法之間或類(lèi)與類(lèi)之間,存在太多的依賴(lài)關(guān)系會(huì)導(dǎo)致代碼可讀性以及可維護(hù)性很差。依賴(lài)倒置原則能夠很好的解決這些問(wèn)題。

什么是依賴(lài)倒置

依賴(lài)倒置原則:程序要依賴(lài)于抽象接口,不要依賴(lài)于具體實(shí)現(xiàn)。簡(jiǎn)單的說(shuō)就是要求對(duì)抽象進(jìn)行編程,不要對(duì)實(shí)現(xiàn)進(jìn)行編程,這樣就降低了客戶(hù)與實(shí)現(xiàn)模塊間的耦合。(節(jié)選自百度百科)

  1. 高層模塊不應(yīng)該依賴(lài)低層模塊,兩者都應(yīng)該依賴(lài)其抽象
  2. 抽象不應(yīng)該依賴(lài)細(xì)節(jié)
  3. 細(xì)節(jié)應(yīng)該依賴(lài)抽象

依賴(lài)倒置好處

  1. 通過(guò)依賴(lài)于接口,隔離了具體實(shí)現(xiàn)類(lèi)
  2. 低一層的變動(dòng)并不會(huì)導(dǎo)致高一層的變動(dòng)
  3. 提高了代碼的容錯(cuò)性、擴(kuò)展性和易于維護(hù)

實(shí)例

 
 
 
 
  1. //  抽象槍類(lèi)
  2. class AbstractGun {
  3.     shoot(){
  4.         throw "Abstract methods cannot be called";
  5.     }
  6. }
  7. //  步槍
  8. class Rifle extends AbstractGun {
  9.     shoot(){
  10.         console.log("步槍射擊...");
  11.     }
  12. }
  13. //  狙擊槍
  14. class AUG extends AbstractGun {
  15.     shoot(){
  16.         console.log("AUG射擊...");
  17.     }
  18. }

從上面的代碼可以看出,步槍與狙擊槍的shoot全部都是依賴(lài)于AbstractGun抽象的槍類(lèi),上述編程滿(mǎn)足了依賴(lài)倒置原則。

接口隔離

什么是接口隔離

接口隔離:客戶(hù)端不應(yīng)該依賴(lài)它不需要的接口;一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上。(節(jié)選自百度百科)

接口隔離原則與單一職責(zé)原則的審視角度不相同。單一職責(zé)原則要求是類(lèi)和接口的職責(zé)單一,注重的職責(zé),這是業(yè)務(wù)邏輯上的劃分。接口隔離原則要求接口的方法盡量少。

接口隔離好處

  1. 避免接口污染
  2. 提高靈活性
  3. 提供定制服務(wù)
  4. 實(shí)現(xiàn)高內(nèi)聚

實(shí)例

 
 
 
 
  1. function mix(...mixins) {
  2.   class Mix {}
  3.   for (let mixin of mixins) {
  4.     copyProperties(Mix, mixin);
  5.     copyProperties(Mix.prototype, mixin.prototype);
  6.   }
  7.   return Mix;
  8. }
  9. function copyProperties(target, source) {
  10.   for (let key of Reflect.ownKeys(source)) {
  11.     if ( key !== "constructor"&& key !== "prototype"&& key !== "name") {
  12.       let desc = Object.getOwnPropertyDescriptor(source, key);
  13.       Object.defineProperty(target, key, desc);
  14.     }
  15.   }
  16. }
  17. class Behavior {
  18.     eat(){
  19.         throw "Abstract methods cannot be used";
  20.     }   
  21.     call(){
  22.         throw "Abstract methods cannot be used";
  23.     }
  24. }
  25. class Action {
  26.     climbTree(){
  27.         throw "Abstract methods cannot be used";
  28.     }
  29. }
  30. class Dog extends Behavior{
  31.     eat(food){
  32.         console.log(`狗正在吃${food}`);
  33.     }
  34.     hungry(){
  35.         console.log("汪汪汪,我餓了")
  36.     }
  37. }
  38. const CatMin = mix(Behavior,Action);
  39. class Cat extends CatMin{
  40.     eat(food){
  41.         console.log(`貓正在吃${food}`);
  42.     }
  43.     hungry(){
  44.         console.log("喵喵喵,我餓了")
  45.     }
  46.     climbTree(){
  47.         console.log("爬樹(shù)很開(kāi)心哦~")
  48.     }
  49. }
  50. let dog = new Dog();
  51. dog.eat("骨頭");
  52. dog.hungry();
  53. let cat = new Cat();
  54. cat.eat("魚(yú)");
  55. cat.hungry();
  56. cat.climbTree();

大家一定要好好分析一下上面的代碼,共有兩個(gè)抽象類(lèi),分別對(duì)應(yīng)不同的行為,Cat與Dog類(lèi)擁有共同的行為,但是Cat又擁有其自己?jiǎn)为?dú)的行為,使用抽象(即接口)繼承其方法,使用接口隔離使其完成各自的工作,各司其職。

迪米特法則

迪米特法則:最少知識(shí)原則(Least Knowledge Principle 簡(jiǎn)寫(xiě)LKP),就是說(shuō)一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象有盡可能少的了解,不和陌生人說(shuō)話(huà)。英文簡(jiǎn)寫(xiě)為: LoD.(節(jié)選自百度百科)

迪米特法則的做法觀念就是類(lèi)間解耦,弱耦合,只有弱耦合了以后,類(lèi)的復(fù)用率才可以提高。一個(gè)類(lèi)應(yīng)該對(duì)其他對(duì)象保持最少的了解。通俗來(lái)講,就是一個(gè)類(lèi)對(duì)自己依賴(lài)的類(lèi)知道的越少越好。因?yàn)轭?lèi)與類(lèi)之間的關(guān)系越密切,耦合度越大,當(dāng)一個(gè)類(lèi)發(fā)生改變時(shí),對(duì)另一個(gè)類(lèi)的影響也越大。

迪米特法則好處

  1. 減少對(duì)象之間的耦合性

實(shí)例

 
 
 
 
  1. class ISystem {
  2.     close(){
  3.         throw "Abstract methods cannot be used";
  4.     }
  5. }
  6. class System extends ISystem{
  7.     saveCurrentTask(){
  8.         console.log("saveCurrentTask")
  9.     }
  10.     closeService(){
  11.         console.log("closeService")
  12.     }
  13.     closeScreen(){
  14.         console.log("closeScreen")
  15.     }
  16.     closePower(){
  17.         console.log("closePower")
  18.     }
  19.     close(){
  20.         this.saveCurrentTask();
  21.         this.closeService();
  22.         this.closeScreen();
  23.         this.closePower();
  24.     }
  25. }
  26. class IContainer{
  27.     sendCloseCommand(){
  28.         throw "Abstract methods cannot be used";
  29.     }
  30. }
  31. class Container extends IContainer{
  32.     constructor(){
  33.         super()
  34.         this.system = new System();
  35.     }
  36.     sendCloseCommand(){
  37.         this.system.close();
  38.     }
  39. }
  40. class Person extends IContainer{
  41.     constructor(){
  42.         super();
  43.         this.container = new Container();
  44.     }
  45.     clickCloseButton(){
  46.        this.container.sendCloseCommand();
  47.     }
  48. }
  49. let person = new Person();
  50. person.clickCloseButton();

上面代碼中Container作為媒介,其調(diào)用類(lèi)不知道其內(nèi)部是如何實(shí)現(xiàn),用戶(hù)去觸發(fā)按鈕,Container把消息通知給計(jì)算機(jī),計(jì)算機(jī)去執(zhí)行相對(duì)應(yīng)的命令。

組合/聚合復(fù)用原則

聚合(Aggregation)表示一種弱的‘擁有’關(guān)系,體現(xiàn)的是A對(duì)象可以包含B對(duì)象但B對(duì)象不是A對(duì)象的一部分。

合成(Composition)則是一種強(qiáng)的'擁有'關(guān)系,體現(xiàn)了嚴(yán)格的部分和整體關(guān)系,部分和整體的生命周期一樣。

組合/聚合:是通過(guò)獲得其他對(duì)象的引用,在運(yùn)行時(shí)刻動(dòng)態(tài)定義的,也就是在一個(gè)對(duì)象中保存其他對(duì)象的屬性,這種方式要求對(duì)象有良好定義的接口,并且這個(gè)接口也不經(jīng)常發(fā)生改變,而且對(duì)象只能通過(guò)接口來(lái)訪問(wèn),這樣我們并不破壞封裝性,所以只要類(lèi)型一致,運(yùn)行時(shí)還可以通過(guò)一個(gè)對(duì)象替換另外一個(gè)對(duì)象。

優(yōu)先使用對(duì)象的合成/聚合將有助于你保持每個(gè)類(lèi)被封裝,并被集中在單個(gè)任務(wù)上,這樣類(lèi)和類(lèi)繼承層次會(huì)保持較小規(guī)模,而且不太可能增長(zhǎng)為不可控制的龐然大物。

組合/聚合復(fù)用原則好處

  1. 新的實(shí)現(xiàn)較為容易,因?yàn)槌?lèi)的大部分功能可通過(guò)繼承關(guān)系自動(dòng)進(jìn)入子類(lèi);
  2. 修改或擴(kuò)展繼承而來(lái)的實(shí)現(xiàn)較為容易。

實(shí)例

 
 
 
 
  1. function mix(...mixins) {
  2.   class Mix {}
  3.   for (let mixin of mixins) {
  4.     copyProperties(Mix, mixin);
  5.     copyProperties(Mix.prototype, mixin.prototype);
  6.   }
  7.   return Mix;
  8. }
  9. function copyProperties(target, source) {
  10.   for (let key of Reflect.ownKeys(source)) {
  11.     if ( key !== "constructor"&& key !== "prototype"&& key !== "name") {
  12.       let desc = Object.getOwnPropertyDescriptor(source, key);
  13.       Object.defineProperty(target, key, desc);
  14.     }
  15.   }
  16. }
  17. class Savings {
  18.     saveMoney(){
  19.         console.log("存錢(qián)");
  20.     }
  21.     withdrawMoney(){
  22.         console.log("取錢(qián)");
  23.     }
  24. }
  25. class Credit {
  26.     overdraft(){
  27.         console.log("透支")
  28.     }
  29. }
  30. const CarMin = mix(Savings,Credit);
  31. class UserCar extends CarMin {
  32.     constructor(num,carUserName){
  33.         super();
  34.         console.log()
  35.         this.carNum = num;
  36.         this.carUserName = carUserName;
  37.     }
  38.     getCarNum(){
  39.         return this.carNum;
  40.     }
  41.     getCarUserName(){
  42.         return this.carUserName;
  43.     }
  44. }
  45. let myCar = new UserCar(123456798,"Aaron");
  46. console.log(myCar.getCarNum());
  47. console.log(myCar.getCarUserName());
  48. myCar.saveMoney();
  49. myCar.withdrawMoney();
  50. myCar.overdraft();

總結(jié)

這些原則在設(shè)計(jì)模式中體現(xiàn)的淋淋盡致,設(shè)計(jì)模式就是實(shí)現(xiàn)了這些原則,從而達(dá)到了代碼復(fù)用、增強(qiáng)了系統(tǒng)的擴(kuò)展性。所以設(shè)計(jì)模式被很多人奉為經(jīng)典。我們可以通過(guò)好好的研究設(shè)計(jì)模式,來(lái)慢慢的體會(huì)這些設(shè)計(jì)原則。


分享名稱(chēng):面向?qū)ο笾叽蠡驹瓌t(JavaScript)
文章地址:http://uogjgqi.cn/article/cdcgphs.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流