前端 IOC 思想簡單實踐

2021-09-24 06:27:16 字數 4417 閱讀 8255

你有沒有過這樣乙個經歷,乙個專案立項之時,什麼模組化啊,什麼抽象啊,什麼解耦啊,什麼可復用元件啊什麼的,哪個高階用哪個,可是專案發展到中期,隨著模組的增加,什麼可復用,能用就行,什麼模組化,載入就行,久而久之,專案越來越大,隨之也越來越臃腫,越來越難以維護,改一處看似簡單的模組,卻發現八桿子打不著的地方居然也被影響了,真真是寫時一時爽,維護時更加爽!

那專案大了,維護成了難題,如何優化呢,怎麼解決呢!

看英文縮寫,是不是有點高大上,其實這個理念在後端是非常常見的,而前端很少涉及到。不過現代前端也可以在專案中實踐了,而且很契合。

三個準則

乙個案例

放著這些個準則不說,先用我們熟悉的macbook來案例來說明下吧! 我們都知道,mac電腦裡面都是乙個個模組組合成的,換算成**就是這樣樣子的:

// screen.ts

export

default

class

screen

// cpu.ts

export

default

class

cpu// battery

// 電池模式,普通模式,低電量,高電量

type tmode = "normal" | "low" | "high";

export

default

class

battery

= )

}// mac.ts

import screen from

"./screen";

import cpu from

"./cpu";

import battery from

"./battery";

export

default

class

macbook

start() , screen is $ and cpu is $`

);}}

// index.ts

import macbook from

"./mac";

let mac = new macbook();

mac.start();

複製**

首先建立乙個index.ts啟動檔案,mac殼子mac.ts,它內部有三個模組,cpuscreenbattery,這個三個屬性分別引用的是檔案外的模組。

**這樣寫,其實沒有什麼問題的,執行index就能看到結果,檢視到這個mac類的配置,那麼,如果說我要設定mac電池配置mode為低電量,那麼我就不得不去mac.ts主模組裡修改電池的配置。

this.battery = new battery();

複製**

這樣改,其實是沒有什麼問題的,但是,mac其中的乙個模組修改了,為什麼殼子mac.ts這個檔案也要跟著動呢,而且這個殼子裡有mac所有的模組依賴,之前測試通過了,這次修改了,能不能保證一定沒有出錯呢,所以這次的模組改動就是我上面說到的問題,那如何改動呢?

第一次優化

// mac.ts

import screen from

"./screen";

import cpu from

"./cpu";

import battery from

"./battery";

inte***ce imac

export

default

class

macbook

start() , screen is $ and cpu is $`

);}}

// index.ts

import macbook from

"./mac";

import battery from

"./battery";

import cpu from

"./cpu";

import screen from

"./screen";

let mac = new macbook();

mac.start();

複製**

將模組的依賴全都放在了啟動檔案index.ts處,無論模組如何改動,殼子模組mac.ts是不是都不用改了,模組之間的耦合度也降低了。

簡單來說,mac.ts是高層模組,battery.ts是底層模組,優化之前mac.ts依賴了battery.ts,是不是違背了ioc的第一條準則呢,優化後的**是將高層次的模組所需要的依賴通過引數傳遞到模組內部,這個方法有乙個專業術語 - 依賴注入(dependency injection)。

所需要傳入的引數型別imac就是所定義的抽象,殼子模組mac.ts就是依賴了這個抽象,而這個抽象也沒有依賴於某個具體的實現。

那麼問題又來了,如果我想給這個mac例項再增加乙個觸控板模組touchpad.ts呢,是不是又要修改殼子模組mac.ts了,難道新增乙個就要修改一次,就沒有乙個通用方案麼?

第二次優化

// mac.ts

type imodule= t | t;

export

default

class

macbook

start()

}// index.ts

import macbook from

"./mac";

import battery from

"./battery";

import cpu from

"./cpu";

import screen from

"./screen";

import touchpad from

"./touchpad";

let mac = new macbook();

mac .use(new cpu())

.use(new screen())

.use([new battery(), new touchpad()])

.start();

複製**

模仿koa載入模組的use方法,可以鏈式,這樣殼子模組mac.ts就完全與低層次模組解藕了,無論mac新增多少個模組它都不會發生修改。mac.ts內部已經看不到什麼業務**了,所有的配置都放在了最外層,即便修改新增也及其方便。

第三次優化

那麼問題又來了,mac.ts對模組可是有要求的,不是任何乙個牌子的模組就能安裝到我的mac上,得按照一定的標準是執行,也就是依照一定的約定,這也就是第三個準則,面向介面程式設計而不是面向實現程式設計,下面就用**來展示這個準則:

// mac.ts

type imodule= t | t;

export

default

class

macbook

start()

}複製**

mac.ts的啟動方法中,我們看到了,對接的模組內部,一定要有乙個init屬性,且這個屬性一定是乙個可執行方法,那麼所對接的模組要如何處理呢:

// cpu.ts

export

default

class

cpu start`);

}}複製**

類似於這樣的,要對接這個殼子,就必須在模組內部實現乙個init方法,這樣這個模組才能在殼子內部起作用。

init方法對於mac.ts來說,只是乙個抽象方法,乙個約定的介面,將實現交給了所來對接的各個模組,這不就是面向介面程式設計 而不要面向實現程式設計最好的詮釋麼!

其實在ioc的術語中,mac.ts更應該稱作為容器(container),上面稱它為殼子比較貼近現實好理解,它跟業務實現其實沒有太大的關聯,僅僅是做一些初始化的操作,所以殼子不應該隨著它所依賴的模組的改變也跟著改變。 所以就需要一種ioc的程式設計思想去優化它,依賴注入只是這種思想的一種實現。

最後說一句,思想才是提高程式設計的最佳手段,而不是學習怎麼用框架!

IOC控制反轉思想

傳統的開發需要程式設計師自己手動的new例項化乙個物件,但這種模式如果使用者需求發生改變往往會需要重新修改 例如 public inte ce userdao public class userdaoimpl implements userdao 使用者需求改變,增加userdao的實現 publi...

PHP 專案實踐中使用的IOC容器思想

1.容器的意思就是乙個全域性變數,裡面存了很多物件,如果要用到某個物件就從裡面取,前提就是要先把物件放進去 2.控制反轉就是把自己的控制權交給別人 3.這兩個結合就是,把自己的控制權交給別人並且建立的物件放進乙個全域性變數裡 4.好處就是可以靈活的修改乙個物件的屬性,而不需要去修改類本身的 clas...

IOC框架Ninject實踐總結

ninject是乙個輕量級的基於.net平台的依賴注入 ioc 框架。所謂的ioc,即控制反轉 inversion of control 它是乙個經典的物件導向程式設計法則,它的作用主要是用來幫助應用程式解耦,並把程式分離成乙個個松耦合高內聚的模組。控制反轉還有乙個名字叫依賴注入 dependenc...