具體地址:http://www.yiyehu.tech/archives/2020/06/01/design-pattern-in-spring
聲明:大綱與部分內容來自於 https://www.runoob.com/design-pattern/design-pattern-intro.html
Contents [hide]
重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
- 對接口編程而不是對實現編程。
- 優先使用對象組合而不是繼承
總共有 23 種設計模式。這些模式可以分爲三大類:創建型模式(Creational Patterns)、結構型模式(Structural Patterns)、行爲型模式(Behavioral Patterns) 。 額外的另一類設計模式:J2EE 設計模式。
設計模式的六大原則
1、開閉原則(Open Close Principle)
開閉原則的意思是:對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,後面的具體設計中我們會提到這點。
避免修改過去的代碼,通過擴展的方式升級系統: 接口和抽象類
2、里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP 是繼承複用的基石,只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用,而派生類也能夠在基類的基礎上增加新的行爲。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。
任何基類可以出現的地方,子類一定可以出現。
3、依賴倒轉原則(Dependence Inversion Principle)
這個原則是開閉原則的基礎,具體內容:針對接口編程,依賴於抽象而不依賴於具體。
4、接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。它還有另外一個意思是:降低類之間的耦合度。由此可見,其實設計模式就是從大型軟件架構出發、便於升級和維護的軟件設計思想,它強調降低依賴,降低耦合。
使用多個接口,每個接口負責一定的功能。
5、迪米特法則,又稱最少知道原則(Demeter Principle)
最少知道原則是指:一個實體應當儘量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
使用行爲型模式:其關注對象之間的通信
6、合成複用原則(Composite Reuse Principle)
合成複用原則是指:儘量使用合成/聚合的方式,而不是使用繼承。
Spring的ApplicationContext在添加對Message,Environment,Event和Source的支持的時候,沒有在BeanFactory上擴展,而是選擇把BeanFactory作爲一個內部屬性調用,對其他配置的支持,通過繼承不同的接口實現(ConfigurableApplicationContext)。
所有的設計模式
序號 | 模式 & 描述 | 包括 |
---|---|---|
1 | 創建型模式 這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 new 運算符直接實例化對象。這使得程序在判斷針對某個給定實例需要創建哪些對象時更加靈活。 |
工廠模式(Factory Pattern) 抽象工廠模式(Abstract Factory Pattern) 單例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
2 | 結構型模式 這些設計模式關注類和對象的組合。繼承的概念被用來組合接口和定義組合對象獲得新功能的方式。 |
適配器模式(Adapter Pattern) 橋接模式(Bridge Pattern) 過濾器模式(Filter、Criteria Pattern) 組合模式(Composite Pattern) 裝飾器模式(Decorator Pattern) 外觀模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
3 | 行爲型模式 這些設計模式特別關注對象之間的通信。 |
責任鏈模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解釋器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 備忘錄模式(Memento Pattern) 觀察者模式(Observer Pattern) 狀態模式(State Pattern) 空對象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 訪問者模式(Visitor Pattern) |
4 | J2EE 模式 這些設計模式特別關注表示層。這些模式是由 Sun Java Center 鑑定的。 |
—————————————————————————— MVC 模式(MVC Pattern) 業務代表模式(Business Delegate Pattern) 組合實體模式(Composite Entity Pattern) 數據訪問對象模式(Data Access Object Pattern) 前端控制器模式(Front Controller Pattern) 攔截過濾器模式(Intercepting Filter Pattern) 服務定位器模式(Service Locator Pattern) 傳輸對象模式(Transfer Object Pattern) |
關係
創建型模式
工廠模式(Factory Pattern)
創建固定類對象的工廠,工廠創建的類可以爲一系列有關的對象,如:一個PCFactory可以有getMouse()和getKeyBoard()等創建一系列相關對象的方法。
抽象工廠模式(Abstract Factory Pattern)
抽象工廠可以形容爲工廠的工廠, 提供一個創建一系列相關或相互依賴對象的接口,而無需指定具體創建的類 。
如: 系統的產品有多於一個的產品族,而系統只消費其中某一族的產品。 PCFactory作爲抽象工廠接口,DellPCFactory和HuaWeiPCFactory就可以作爲 抽象工廠 的工廠,每個不同的工廠生產不同品牌的產品。
如數據庫操作:每一個不同數據庫(如MySQL和SQLServer)工廠協議可以生成繼承同一個接口但是細節不同的連接。而他們都會繼承一個接口,其作爲抽象工廠。
單例模式(Singleton Pattern)
持久化一個實例並保存,每一次請求的對象都是同一個。
原型模式(Prototype Pattern)
與通過對一個類進行實例化來構造新對象不同的是,原型模式是通過拷貝一個現有對象生成新對象的。淺拷貝實現 Cloneable,重寫,深拷貝是通過實現 Serializable 讀取二進制流。
使用場景: 1、資源優化場景。
2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。
3、性能和安全要求的場景。
4、通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。
5、一個對象多個修改者的場景,且對象中沒有共享資源。
6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。
7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然後由工廠方法提供給調用者。原型模式已經與 Java 融爲渾然一體,大家可以隨手拿來使用。
8、 當一個類的實例只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。
建造者模式(Builder Pattern)
一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立於其他對象的。
場景:
- 如果一個對象有非常複雜的內部結構,在用戶不知道對象的建造過程和細節的情況下就可以直接創建複雜的對象。
- 想把複雜對象的創建和使用分離。
Spring UriComponentsBuilder與 UriComponents
- public static UriComponentsBuilder from*()和其構造函數用以初始化UriComponentsBuilder獲得其實例。
- public UriComponentsBuilder function(…)用來配置屬性(也可以在初始化的時候賦值)
- public UriComponents build()用來構建 UriComponents
當然,所有的一切都可以通過類本身進行構建,不需要Builder,但是由於太複雜,比如誇張一點,有100個屬性,其中非常多的非必填,這些屬性的組合非常多,用構造函數表示則非常多,如果全部在初始化賦值,會有非常多的屬性賦值爲null,這個時候就可以用建造者模式。其對類內屬性的操作用:
public Builder param(int param ) {
this.param = param;
return this;
}
// 一般構建都會寫成:
Object object= Builder.instance().para().otherpara().operation().otherOperation().build()
結構型模式
適配器模式(Adapter Pattern)
適配器模式(Adapter Pattern)是作爲兩個不兼容的接口之間的橋樑。
適配器繼承或依賴已有的對象,實現想要的目標接口。
適配器不是在詳細設計時添加的,而是解決正在服役的項目的問題。
https://www.cnblogs.com/tongkey/p/7919401.html
spring案例: spring事件與監聽器 ApplicationListenerMethodAdapter
首先簡要介紹一下spring的事件監聽:
spring事件監聽是在監聽的方法上使用@ListenerEvent進行註冊,最終把這個方法註冊爲一個監聽器。
ApplicationListenerMethodAdapter
實現了GenericApplicationListener
接口,他有兩個作用,一個是保存方法的一些信息,第二是通過反射的方法實現對這些方法的調用(對方法的調用寫在對GenericApplicationListener實現方法中,本來GenericApplicationListener中實現的東西由於需要使用到反射所以GenericApplicationListener是一個接口,實現全部在ApplicationListenerMethodAdapter中)。這就是一個方法調用到監聽器的一個轉變或者說適配。
最終這些監聽器被保存在AbstractApplicationContext的Set<> applicationListeners
中。
橋接模式(Bridge Pattern)
橋接模式即將抽象部分與它的實現部分分離開來,使他們都可以獨立變化。
抽象化:其概念是將複雜物體的一個或幾個特性抽出去而只注意其他特性的行動或過程。在面向對象就是將對象共同的性質抽取出去而形成類的過程。
實現化:針對抽象化給出的具體實現。它和抽象化是一個互逆的過程,實現化是對抽象化事物的進一步具體化。
脫耦:脫耦就是將抽象化和實現化之間的耦合解脫開,或者說是將它們之間的強關聯改換成弱關聯,將兩個角色之間的繼承關係改爲關聯關係。
給一個案例:編寫一個可以畫不同顏色不同形狀的程序。
顏色和形狀屬於不同的維度——抽象出來;
不同的顏色實現、不同的形狀實現——實現化;
脫耦合
具體實現就是由一端保持另一端的引用,在使用到這部分的時候調用就行。一端到另一端就是橋接。
public class Shape{
DrawColor drawColor;
public Shape(DrawColor drawColor){
this.drawColor = drawColor;
}
public void draw(){
drowShape();
drawColor.drawColor();
}
}
過濾器(標準)模式(Filter、Criteria Pattern)
接力型,這種模式允許開發人員使用不同的標準來過濾一組對象,通過邏輯運算以解耦的方式把它們連接起來。這種類型的設計模式屬於結構型模式,它結合多個標準來獲得單一標準。
組合模式(Composite Pattern)
用於把一組相似的對象當作一個單一的對象 。
將對象組合成樹形結構以表示”部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
組合模式使得用戶對單個對象和組合對象的使用具有一致性。 這句話就是組合模式的應用過程。Listener,監聽器就是典型的場景。對一個事件註冊了多個監聽器,可以使用組合模式,將多個監聽器保存在組合模式的監聽器中,事件觸發則循環調用所有監聽器的方法。
任何對於某個點的共同不相互影響的操作都可以使用組合模式,其實就是遍歷操作。
如:org.springframework.statemachine.action.CompositeActionListener
裝飾器模式(Decorator Pattern)
裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。不使用繼承的方式。
在不想增加很多子類的情況下擴展類。
具體擴展類重寫父類方法 。
舉個栗子:食品加工廠的工人都實現同一個接口worker有着同一個方法process。實現 worker 表示不同類型的工人。這時有一個需求是對部分類型的工人在其加工之前或之後加入一些動作。就可以使用裝飾者模式。
public interface Worker{ void process();}
public ATypeWorker implements Worker{ public void process(){ ...doA();}}
public BTypeWorker implements Worker{ public void process(){ ...doB();}}
public CTypeWorker implements Worker{ public void process(){ ...doC();}}
public WorkerDecorator implements Worker{
Worker worker;
public WorkerDecorator(Worker worker){
this.worker = worker;
}
public void woker(){
doSomethingNeedBefore();
worker.process();
doSomethingNeedAfter();
}
}
看起來像是可以用AOP切面添加執行方法,但是裝飾者模式是爲了在不通過繼承來擴展類的方法,且可以橫向擴展(一次擴展多個子類)。
外觀模式(Facade Pattern)
意圖:爲子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
主要解決:降低訪問複雜系統的內部子系統時的複雜度,簡化客戶端與之的接口。
何時使用: 1、客戶端不需要知道系統內部的複雜聯繫,整個系統只需提供一個”接待員”即可。 2、定義系統的入口。
舉個栗子:Dubbo
享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)主要用於減少創建對象的數量,以減少內存佔用和提高性能。這種類型的設計模式屬於結構型模式,它提供了減少對象數量從而改善應用所需的對象結構的方式。
減少對象的創建,降低系統的內存,使效率提高。
應用實例: 1、JAVA 中的 String,如果有則返回,如果沒有則創建一個字符串保存在字符串緩存池裏面。 2、數據庫的數據池。
大概意思就是保存一些對象,防止對同一類對象反覆的創建銷燬。
具體實現:存起來,如HashMap存一下,通過String標識符獲取。
代理模式(Proxy Pattern)
代理模式給某一個對象提供一個代理對象,並由代理對象控制對原對象的引用。通俗的來講代理模式就是我們生活中常見的中介。
注意事項: 1、和適配器模式的區別:適配器模式主要改變所考慮對象的接口,而代理模式不能改變所代理類的接口。 2、和裝飾器模式的區別:裝飾器模式爲了增強功能,而代理模式是爲了加以控制。
靜態代理模式和裝飾器模式沒有什麼區別,在代理類不多的情況下,使用靜態代理,實例和裝飾器模式是一樣的。只不過是目的不一樣,裝飾器模式是爲了在其本身的行爲模式下進行拓展,代理是爲加以控制(添加日誌,處理參數……)
主要還是動態代理,通過反射實現。
案例講解:https://www.cnblogs.com/carpenterlee/p/8241042.html
https://www.cnblogs.com/carpenterlee/p/8241042.html
行爲型模式
責任鏈模式(Chain of Responsibility Pattern)
意圖:避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,並且沿着這條鏈傳遞請求,直到有對象處理它爲止。
主要解決:職責鏈上的處理者負責處理請求,客戶只需要將請求發送到職責鏈上即可,無須關心請求的處理細節和請求的傳遞,所以職責鏈將請求的發送者和請求的處理者解耦。
所有的處理器都在一個鏈表上,每處理一個消息都要從鏈表頭到表尾。
命令模式(Command Pattern)
請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。
將一個請求封裝成一個對象,從而使可以用不同的請求對客戶進行參數化。
優點: 1、降低了系統耦合度。 2、新的命令可以很容易添加到系統中去。
案例講解:https://www.cnblogs.com/jmcui/p/10042235.html
1、命令(Command):爲所有命令聲明瞭一個接口。調用命令對象的 execute()方法,就可以讓接收者進行相關的操作。這個接口也具備一個 undo() 方法。
https://www.cnblogs.com/jmcui/p/10042235.html
2、具體命令(ConcreteCommand):實現命令接口,定義了動作和接收者之間的綁定關係。調用者只要調用 execute() 就可以發出請求,然後由 ConcreteCommand 調用接收者的一個或多個動作。
3、請求者(Invoker):持有一個命令對象,有一個行動方法,在某個時間點調用命令對象的 execute() 方法,將請求付諸實行。
4、接收者(Receiver):接收者知道如何進行必要的動作,實現這個請求。任何類都可以當接收者。最後執行動作的那個對象。
5、客戶端(Client):創建一個具體命令(ConcreteCommand)對象並確定其接收者,包括把其他角色串連在一起。
一句話總結:Invoker保存了所有的command(ConcreteCommand),客戶端使用參數調用具體的ConcreteCommand,command調用與Receiver關聯的方法執行一個或多個動作。
類比:Spring的Controller
DispacherServlet相當於Invoker,然後所有的Controller下的RequestMapping都會被註冊爲MappingRegistration,作爲一個Handler(這就相當於一個命令),這些MappingRegistration中保存着路徑與方法,最終通過路徑尋找到Handler調用這些方法。這些方法中再調用一個或多個Service,這些Service也就相當於Receiver。
解釋器模式(Interpreter Pattern)
意圖:給定一個語言,定義它的文法表示,並定義一個解釋器,這個解釋器使用該標識來解釋語言中的句子。
如何解決:構建語法樹,定義終結符與非終結符。
1、非終結符可以bai再分成更細的東西。
2、不是終結符的都是非終結符。非終結符可理解爲一個可拆分元素,而終結符是不可拆分的最小元素。終結符號就是語言中用到的基本元素,名詞、動詞、形容詞、助詞等等基本語言單位。
應用實例:編譯器、運算表達式計算、 SQL 解析、符號處理引擎、Spring Expression Language(SpEL)。
SpEL是一種由Spring的org.springframework.expression.ExpressionParser實現分析和執行的語言。使用作爲字符串給出的Spel表達式,並將Spel表達式轉換爲org.springframework.expression.Expression的實例。
迭代器模式(Iterator Pattern)
意圖:提供一種方法順序訪問一個聚合對象中各個元素, 而又無須暴露該對象的內部表示。
用以遍歷一個聚合對象。
關鍵代碼:定義接口:hasNext, next。
應用實例:JAVA 中的 iterator
。Python的__iter__() ,iter()
中介者模式(Mediator Pattern)
中介者模式(Mediator Pattern)是用來降低多個對象和類之間的通信複雜性。這種模式提供了一箇中介類,該類通常處理不同類之間的通信,並支持松耦合,使代碼易於維護。中介者模式屬於行爲型模式。
意圖:用一箇中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
主要解決:對象與對象之間存在大量的關聯關係,這樣勢必會導致系統的結構變得很複雜,同時若一個對象發生改變,我們也需要跟蹤與之相關聯的對象,同時做出相應的處理。
何時使用:多個類相互耦合,形成了網狀結構。
如何解決:將上述網狀結構分離爲星型結構。
關鍵代碼:對象 Colleague 之間的通信封裝到一個類中單獨處理。
應用實例: 1、中國加入 WTO 之前是各個國家相互貿易,結構複雜,現在是各個國家通過 WTO 來互相貿易。 2、機場調度系統。 3、MVC 框架,其中C(控制器)就是 M(模型)和 V(視圖)的中介者。
優點: 1、降低了類的複雜度,將一對多轉化成了一對一。 2、各個類之間的解耦。 3、符合迪米特原則
備忘錄模式(Memento Pattern)
備忘錄模式(Memento Pattern)保存一個對象的某個狀態,以便在適當的時候恢復對象。備忘錄模式屬於行爲型模式。
1、需要保存/恢復數據的相關狀態場景。 2、提供一個可回滾的操作。
案例:1、後悔藥。 2、打遊戲時的存檔。 3、Windows 裏的 ctri + z。 4、IE 中的後退。 4、數據庫的事務管理。
觀察者模式(Observer Pattern)
當對象間存在一對多關係時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬於行爲型模式。
意圖:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
組合模式中我講過一個例子,這個也可以看做是一個一對多的場景:
Listener,監聽器就是典型的場景。對一個事件註冊了多個監聽器,可以使用組合模式,將多個監聽器保存在組合模式的監聽器中,事件觸發則循環調用所有監聽器的方法。
任何對於某個點的共同不相互影響的操作都可以使用組合模式,其實就是遍歷操作。
如:org.springframework.statemachine.action.CompositeActionListener
因爲CompositeActionListener是觀察者模式和組合模式的組合。還有一個例子,Spring的事件監聽,這就是一個觀察者模式,一個Event被Publish,則所有監聽這個Event事件的監聽器都將調用並執行,spring的事件監聽使用了適配器模式。
狀態模式(State Pattern)
在狀態模式(State Pattern)中,類的行爲基於它的狀態改變。
意圖:允許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類。
主要解決:對象的行爲依賴於它的狀態(屬性),並且可以根據它的狀態改變而改變它的相關行爲。
何時使用:代碼中包含大量與對象狀態有關的條件語句。
如何解決:將各種具體的狀態類抽象出來。
代替if else
空對象模式(Null Object Pattern)
空對象:不包含信息,不做任何操作的對象。
該空對象類用於需要檢查空值的地方。替代Null。
策略模式(Strategy Pattern)
意圖:定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。
菜鳥教程或者其他一些網上的博客,把策略模式用作解決if…else所帶來的複雜和難以維護 ? ???? ?
怎麼可能是這種回事。解決if…else 不是重點。
策略模式的實現是爲了動態地讓一個對象在許多行爲中選擇一種行爲;動態地在幾種算法中選擇一種;
實現某一方面的特性,通過實現統一的接口就可以了,然後類中有這個接口作爲他的實現類的引用類型。不同實現類相互之間替換。
策略模式注意點:
https://blog.csdn.net/qq_39969226/article/details/88069038
1.分析項目中變化部分與不變部分
2.多用組合少用繼承;用行爲類組合,而不是行爲的繼承。更有彈性。
3.設計模式沒有相應的庫直接使用,有些庫或框架本身就用某種設計模式設計的。
和適配器模式、裝飾器模式、代理模式的區別
雖然目的不同但是適配器模式、裝飾器模式、代理模式這三者本身都是需要實現接口(需要適配的接口,需要裝飾擴展的接口、需要代理控制的接口)的。
但是策略模式不同,他需要這個功能,但是隻是需要用,並不屬於這個特性的類。如人類可以手拿工具完成一些事情,但是並不需要實現工具的接口(或繼承類,人不等於工具),只需要保持一個工具具體實現類的對象的一個引用,通過工具所做的事情交給工具的接口。
public interface Tool{
void useTool();
}
public class People{
private Tool tool;
public People(Tool tool){
this.tool = tool;
}
public void useToolDoSomething(){
tool.useTool();
}
}
感覺沒有必要作爲一個模式
模板模式(Template Pattern)
在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬於行爲型模式。
意圖:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
主要解決:一些方法通用,卻在每一個子類都重新寫了這一方法。
Spring中大量使用了模板模式,比如ApplicationContext中獲取BeanFactory的方法(如:getAutowireCapableBeanFactory
),最終是通過getBeanFactory
這個方法獲得的,代碼如下。
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
這個方法就是抽象的,其具體實現由ApplicationContext的子類(AbstractRefreshableApplicationContext、GenericApplicationContext)實現,這個方法是通用的,但是怎麼實現由子類自己決定,父類不管,所以就抽象了出來,使得子類必須要實現它。
或者說抽象這個概念本身就是爲了把公共的代碼抽取出來公共實現,其他方法由子類按照自己的想法實現。
訪問者模式(Visitor Pattern)
意圖:主要將數據結構與數據操作分離。
https://www.jianshu.com/p/1f1049d0a0f4
J2EE 模式
MVC 模式(MVC Pattern)
MVC 模式代表 Model-View-Controller(模型-視圖-控制器) 模式。這種模式用於應用程序的分層開發。
- Model(模型) – 模型代表一個存取數據的對象或 JAVA POJO。它也可以帶有邏輯,在數據變化時更新控制器。
- View(視圖) – 視圖代表模型包含的數據的可視化。
- Controller(控制器) – 控制器作用於模型和視圖上。它控制數據流向模型對象,並在數據變化時更新視圖。它使視圖與模型分離開。