前言:設計模式( Design pattern )是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石同樣。只有精通了設計模式,纔敢說真正理解了軟件工程。能夠說,設計模式是每個架構師所必備的技能之一。想要精通設計模式,必需要先搞清楚設計模式的六大原則。java
核心思想:單一原則很簡單,就是將一組相關性很高的函數、數據封裝到一個類中。換句話說,一個類應該有職責單一。算法
問題描述:假若有類Class1完成職責T1,T2,當職責T1或T2有變動須要修改時,有可能影響到該類的另一個職責正常工做。編程
好處:類的複雜度下降、可讀性提升、可維護性提升、擴展性提升、下降了變動引發的風險。設計模式
需注意:單一職責原則提出了一個編寫程序的標準,用「職責」或「變化緣由」來衡量接口或類設計得是否優良,可是「職責」和「變化緣由」都是不能夠度量的,因項目和環境而異。數組
核心思想:儘可能經過擴展軟件實體來解決需求變化,而不是經過修改已有的代碼來完成變化bash
通俗來說: 一個軟件產品在生命週期內,都會發生變化,既然變化是一個既定的事實,咱們就應該在設計的時候儘可能適應這些變化,以提升項目的穩定性和靈活性。數據結構
核心思想:在使用基類的的地方能夠任意使用其子類,能保證子類完美替換基類。架構
通俗來說:只要父類能出現的地方子類就能出現。反之,父類則未必能勝任。app
好處:加強程序的健壯性,即便增長了子類,原有的子類還能夠繼續運行。框架
需注意:若是子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生「畸變」,則建議斷開父子繼承關係 採用依賴、聚合、組合等關係代替繼承。
核心思想:高層模塊不該該依賴底層模塊,兩者都該依賴其抽象;抽象不該該依賴細節;細節應該依賴抽象;
說明:高層模塊就是調用端,底層模塊就是具體實現類。抽象就是指接口或抽象類。細節就是實現類。
通俗來說:依賴倒置原則的本質就是經過抽象(接口或抽象類)使個各種或模塊的實現彼此獨立,互不影響,實現模塊間的鬆耦合。
問題描述:類A直接依賴類B,假如要將類A改成依賴類C,則必須經過修改類A的代碼來達成。這種場景下,類A通常是高層模塊,負責複雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操做;假如修改類A,會給程序帶來沒必要要的風險。
解決方案:將類A修改成依賴接口interface,類B和類C各自實現接口interface,類A經過接口interface間接與類B或者類C發生聯繫,則會大大下降修改類A的概率。
好處:依賴倒置的好處在小型項目中很難體現出來。但在大中型項目中能夠減小需求變化引發的工做量。使並行開發更友好。
核心思想:類間的依賴關係應該創建在最小的接口上
通俗來說:創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。也就是說,咱們要爲各個類創建專用的接口,而不要試圖去創建一個很龐大的接口供全部依賴它的類去調用。
問題描述:類A經過接口interface依賴類B,類C經過接口interface依賴類D,若是接口interface對於類A和類B來講不是最小接口,則類B和類D必須去實現他們不須要的方法。 需注意:
接口儘可能小,可是要有限度。對接口進行細化能夠提升程序設計靈活性,可是若是太小,則會形成接口數量過多,使設計複雜化。因此必定要適度
提升內聚,減小對外交互。使接口用最少的方法去完成最多的事情
爲依賴接口的類定製服務。只暴露給調用的類它須要的方法,它不須要的方法則隱藏起來。只有專一地爲一個模塊提供定製服務,才能創建最小的依賴關係。
核心思想:類間解耦。
通俗來說: 一個類對本身依賴的類知道的越少越好。自從咱們接觸編程開始,就知道了軟件編程的總的原則:低耦合,高內聚。不管是面向過程編程仍是面向對象編程,只有使各個模塊之間的耦合儘可能的低,才能提升代碼的複用率。低耦合的優勢不言而喻,可是怎麼樣編程才能作到低耦合呢?那正是迪米特法則要去完成的。
開閉原則是總綱,他告訴咱們要對擴展開放,對修改關閉;
單一職責原則告訴咱們實現類要職責單一;
里氏替換原則告訴咱們不要破壞繼承體系;
依賴倒置原則告訴咱們要面向接口編程;
接口隔離原則告訴咱們在設計接口的時候要精簡單一;
迪米特法則告訴咱們要下降耦合。
定義
確保單例類只有一個實例,而且這個單例類提供一個函數接口讓其餘類獲取到這個惟一的實例。
若是某個類,建立時須要消耗不少資源,即new出這個類的代價很大;或者是這個類佔用不少內存,若是建立太多這個類實例會致使內存佔用太多。上述狀況下就應該使用單例模式
實際應用
//獲取WindowManager服務引用
WindowManager wm = (WindowManager) getSystemService(getApplication().WINDOW_SERVICE);
其內部就是經過單例的方式持有一個WindowManager並返回這個對象
複製代碼
定義
將一個複雜對象的構造與它的表示分離,使得一樣的構造過程能夠建立不一樣的表示。 主要是在建立某個對象時,須要設定不少的參數(經過setter方法),可是這些參數必須按照某個順序設定,或者是設置步驟不一樣會獲得不一樣結果。
示例
各種自定義Dialog
AlertDialog.Builer builder=new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon)
.setTitle("title")
.setMessage("message")
.setPositiveButton("Button1",
new DialogInterface.OnclickListener(){
public void onClick(DialogInterface dialog,int whichButton){
setTitle("click");
}
})
.create()
.show();
複製代碼
定義
用原型實例指定建立對象的種類,並經過拷貝這些原型建立新的對象。 能夠在類的屬性特別多,可是又要常常對類進行拷貝的時候能夠用原型模式,這樣代碼比較簡潔,並且比較方便。
拷貝時要注意淺拷貝與深拷貝
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
//克隆副本
Intent copyIntent=(Intetn)shareIntent.clone();
複製代碼
定義
創建一個工廠(一個函數或一個類方法)來製造新的對象。
public Object getSystemService(String name) {
if (getBaseContext() == null) {
throw new IllegalStateException("System services not available to Activities before onCreate()");
}
//........
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
//.......
return super.getSystemService(name);
}
複製代碼
在getSystemService方法中就是用到了簡單工廠模式,根據傳入的參數決定建立哪一個對象,因爲這些對象以單例模式提早建立好了,因此此處不用new了,直接把單例返回就好。
定義
是定義一個建立產品對象的工廠接口,讓其子類決定實例化哪個類,將實際建立工做推遲到子類當中。
public abstract class Product {
public abstract void method();
}
public class ConcreteProduct extends Prodect {
public void method(){
System.out.println("我是具體產品!");
}
}
public abstract class Factory{
public abstract Product createProduct();
}
public class ConcreteFactory extends Factory{
public Product createProduct(){
return new ConcreteProductA();
}
}
複製代碼
抽象工廠模式:爲建立一組相關或者是相互依賴的對象提供一個接口,而不須要制定他們的具體類 看個例子吧,將它跟工廠方法模式作個對比:
public abstract class AbstractProductA{
public abstract void method();
}
public abstract class AbstractProdectB{
public abstract void method();
}
public class ConcreteProductA1 extends AbstractProductA{
public void method(){
System.out.println("具體產品A1的方法!");
}
}
public class ConcreteProductA2 extends AbstractProductA{
public void method(){
System.out.println("具體產品A2的方法!");
}
}
public class ConcreteProductB1 extends AbstractProductB{
public void method(){
System.out.println("具體產品B1的方法!");
}
}
public class ConcreteProductB2 extends AbstractProductB{
public void method(){
System.out.println("具體產品B2的方法!");
}
}
public abstract class AbstractFactory{
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
public class ConcreteFactory1 extends AbstractFactory{
public AbstractProductA createProductA(){
return new ConcreteProductA1();
}
public AbstractProductB createProductB(){
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 extends AbstractFactory{
public AbstractProductA createProductA(){
return new ConcreteProductA2();
}
public AbstractProductB createProductB(){
return new ConcreteProductB2();
}
}
複製代碼
其實Android源碼中對抽象工廠出現的比較少,好在抽象工廠方法並不複雜,很容易記住,咱們能夠從Service中去理解,Service的onBind方法能夠當作是一個工廠方法,從framework角度來看Service,能夠當作是一個具體的工廠,這至關於一個抽象工廠方法模式的雛形。
public class BaseService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent){
return new Binder();
}
}
複製代碼
定義
有一系列的算法,將每一個算法封裝起來(每一個算法能夠封裝到不一樣的類中),各個算法之間能夠替換,策略模式讓算法獨立於使用它的客戶而獨立變化。
public abstract class BaseAdvertManager {
protected abstract void doLoadAdvert();
}
public class FacebookAdvertManager extends BaseAdvertManager {
@Override
protected void doLoadAdvert() {
Log.v(TAG, "加載Facebook廣告");
}
}
public class AdmobAdvertManager extends BaseAdvertManager {
@Override
protected void doLoadAdvert() {
Log.v(TAG, "加載Admob廣告");
}
}
複製代碼
Android在屬性動畫中使用時間插值器的時候就用到了策略模式。在使用動畫時,你能夠選擇線性插值器LinearInterpolator、加速減速插值器AccelerateDecelerateInterpolator、減速插值器DecelerateInterpolator以及自定義的插值器。這些插值器都是實現根據時間流逝的百分比來計算出當前屬性值改變的百分比。經過根據須要選擇不一樣的插值器,實現不一樣的動畫效果。
定義
狀態模式中,行爲是由狀態來決定的,不一樣狀態下有不一樣行爲。狀態模式和策略模式的結構幾乎是如出一轍的,主要是他們表達的目的和本質是不一樣。
public interface TvState{
public void nextChannerl();
public void prevChannerl();
public void turnUp();
public void turnDown();
}
public class PowerOffState implements TvState{
public void nextChannel(){}
public void prevChannel(){}
public void turnUp(){}
public void turnDown(){}
}
public class PowerOnState implements TvState{
public void nextChannel(){
System.out.println("下一頻道");
}
public void prevChannel(){
System.out.println("上一頻道");
}
public void turnUp(){
System.out.println("調高音量");
}
public void turnDown(){
System.out.println("調低音量");
}
}
public interface PowerController{
public void powerOn();
public void powerOff();
}
public class TvController implements PowerController{
TvState mTvState;
public void setTvState(TvStete tvState){
mTvState=tvState;
}
public void powerOn(){
setTvState(new PowerOnState());
System.out.println("開機啦");
}
public void powerOff(){
setTvState(new PowerOffState());
System.out.println("關機啦");
}
public void nextChannel(){
mTvState.nextChannel();
}
public void prevChannel(){
mTvState.prevChannel();
}
public void turnUp(){
mTvState.turnUp();
}
public void turnDown(){
mTvState.turnDown();
}
}
public class Client{
public static void main(String[] args){
TvController tvController=new TvController();
tvController.powerOn();
tvController.nextChannel();
tvController.turnUp();
tvController.powerOff();
//調高音量,此時不會生效
tvController.turnUp();
}
}
複製代碼
Android源碼中不少地方都有用到狀態模式,舉一個例子,就是Android的WIFI管理模塊。當WIFI開啓時,自動掃描周圍的接入點,而後以列表的形式展現;當wifi關閉時則清空。這裏wifi管理模塊就是根據不一樣的狀態執行不一樣的行爲。
與策略模式的區別
狀態模式的行爲是平行的、不可替換的,策略模式是屬於對象的行爲模式,其行爲是彼此獨立可相互替換的。
定義
使多個對象都有機會處理請求,從而避免請求的發送者和接受者直接的耦合關係,將這些對象連成一條鏈,並沿這條鏈傳遞該請求,直到有對象處理它爲止。
/**
* 抽象處理者
*/
public abstract class Handler {
/**
* 持有後繼的責任對象
*/
protected Handler successor;
/**
* 示意處理請求的方法,雖然這個示意方法是沒有傳入參數的
* 但實際是能夠傳入參數的,根據具體須要來選擇是否傳遞參數
*/
public abstract void handleRequest();
/**
* 取值方法
*/
public Handler getSuccessor() {
return successor;
}
/**
* 賦值方法,設置後繼的責任對象
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
/**
* 具體處理者
*/
public class ConcreteHandler extends Handler {
/**
* 處理方法,調用此方法處理請求
*/
@Override
public void handleRequest() {
/**
* 判斷是否有後繼的責任對象
* 若是有,就轉發請求給後繼的責任對象
* 若是沒有,則處理請求
*/
if(getSuccessor() != null)
{
System.out.println("放過請求");
getSuccessor().handleRequest();
}else
{
System.out.println("處理請求");
}
}
}
/**
* 發起請求的客戶類
*/
public class Client {
public static void main(String[] args) {
//組裝責任鏈
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//提交請求
handler1.handleRequest();
}
}
複製代碼
在Android處理點擊事件時,父View先接收到點擊事件,若是父View不處理則交給子View,把責任依次往下傳遞;還有Java的異常捕獲機制也是責任鏈模式的一種體現
定義
給定一個語言,定義它的語法,並定義一個解釋器,這個解釋器用於解析語言。
這個用到的地方也很多,其一就是Android的四大組件須要在AndroidManifest.xml中定義,其實AndroidManifest.xml就定義了,等標籤(語句)的屬性以及其子標籤,規定了具體的使用(語法),經過PackageManagerService(解釋器)進行解析。
定義
命令模式將每一個請求封裝成一個對象,從而讓用戶使用不一樣的請求把客戶端參數化;將請求進行排隊或者記錄請求日誌,以及支持可撤銷操做。 舉個例子來理解:當咱們點擊「關機」命令,系統會執行一系列操做,好比暫停事件處理、保存系統配置、結束程序進程、調用內核命令關閉計算機等等,這些命令封裝從不一樣的對象,而後放入到隊列中一個個去執行,還能夠提供撤銷操做。
在Android事件機制中,底層邏輯對事件的轉發處理。每次的按鍵事件會被封裝成NotifyKeyArgs對象,經過InputDispatcher封裝具體的事件操做。還有一個例子就是咱們使用的Runnable,咱們可使用它來封裝本身想作的操做,而後交給Handler按順序處理,或者在處理前remove取消掉
定義
有時被稱做發佈/訂閱模式,其定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知全部觀察者對象,使它們可以自動更新本身。
ListView的適配器有個notifyDataSetChange()函數,就是通知ListView的每一個Item,數據源發生了變化,各個子Item須要從新刷新一下。
定義
在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在對象以外保存這個狀態,這樣,之後就可將對象恢復到原先保存的狀態中。
Activity的onSaveInstanceState和onRestoreInstanceState就是用到了備忘錄模式,分別用於保存和恢復。
定義
提供一種方法順序訪問一個容器對象中的各個元素,而不須要暴露該對象的內部表示。 迭代器模式是與集合共生共死的,通常來講,咱們只要實現一個集合,就須要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有本身的迭代器。假如咱們要實現一個這樣的新的容器,固然也須要引入迭代器模式,給咱們的容器實現一個迭代器。
Java的Iterator就是一個抽象迭代器,經過實現這個接口各個集合能夠提供本身定製的具體迭代器,感興趣的能夠直接查看源碼 雖然咱們使用集合的場景很是多,可是實際使用到迭代器的卻比較少,對於比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較爲繁瑣,好比ArrayList,咱們更傾向於使用for循環來遍歷,可是針對hash表之類的集合來講,引入迭代器就反而簡單多了。同時咱們也能夠經過自定義迭代器來對有序列表提供正序遍歷或者倒序遍歷,用戶只須要獲得迭代器就能夠遍歷了,而不須要關心具體遍歷算法。
Android源碼中,最典型的就是Cursor用到了迭代器模式,當咱們使用SQLiteDatabase的query方法時,返回的就是Cursor對象,以後再經過Cursor去遍歷數據
cursor.moveToFirst();
do{
//cursor.getXXX(int);
}while(cursor.moveToNext);
複製代碼
定義
定義一個操做中的算法框架,而將一些步驟延遲到子類中,使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定的步驟。
咱們知道,啓動一個Activity過程很是複雜,若是讓開發者每次本身去調用啓動Activity過程無疑是一場噩夢。好在啓動Activity大部分代碼時不一樣的,可是有不少地方須要開發者定製。也就是說,總體算法框架是相同的,可是將一些步驟延遲到子類中,好比Activity的onCreate、onStart等等。這樣子類不用改變總體啓動Activity過程便可重定義某些具體的操做了~。
定義:封裝一些做用於某種數據結構中各元素的操做,它能夠在不改變這個數據結構的前提下定義做用於這些元素的新的操做。
訪問者模式是23種設計模式中最複雜的一個,但他的使用率並不高,大部分狀況下,咱們不須要使用訪問者模式,少數特定的場景才須要。
Android中運用訪問者模式,其實主要是在編譯期註解中,編譯期註解核心原理依賴APT(Annotation Processing Tools),著名的開源庫好比ButterKnife、Dagger、Retrofit都是基於APT。
定義:中介者模式包裝了一系列對象相互做用的方式,使得這些對象沒必要相互明顯調用,從而使他們能夠輕鬆耦合。當某些對象之間的做用發生改變時,不會當即影響其餘的一些對象之間的做用保證這些做用能夠彼此獨立的變化,中介者模式將多對多的相互做用轉爲一對多的相互做用。
何時用中介者模式呢?其實,中介者對象是將系統從網狀結構轉爲以調停者爲中心的星型結構。
舉個簡單的例子,一臺電腦包括:CPU、內存、顯卡、IO設備。其實,要啓動一臺計算機,有了CPU和內存就夠了。固然,若是你須要鏈接顯示器顯示畫面,那就得加顯卡,若是你須要存儲數據,那就要IO設備,可是這並非最重要的,它們只是分割開來的普通零件而已,咱們須要同樣東西把這些零件整合起來,變成一個完總體,這個東西就是主板。主板就是起到中介者的做用,任何兩個模塊之間的通訊都會通過主板協調。
那麼Android中那些地方用到了中介者模式呢?在Binder機制中,就用到了中介者模式,對Binder不是很熟悉的童鞋請參考個人《 簡單明瞭,完全地理解Binder》。咱們知道系統啓動時,各類系統服務會向ServiceManager提交註冊,即ServiceManager持有各類系統服務的引用 ,當咱們須要獲取系統的Service時,好比ActivityManager、WindowManager等(它們都是Binder),首先是向ServiceManager查詢指定標示符對應的Binder,再由ServiceManager返回Binder的引用。而且客戶端和服務端之間的通訊是經過Binder驅動來實現,這裏的ServiceManager和Binder驅動就是中介者。
定義:爲其餘類提供一種代理以控制這個對象的訪問。
其實代理模式咱們平時用的也比較多,其實比較好理解,就是當咱們須要對一個對象進行訪問時,咱們不直接對這個對象進行訪問,而是訪問這個類的代理類,代理類能幫咱們執行咱們想要的操做。代理模式比較容易理解,既然你來看這篇文章相信你對代理模式不陌生。
咱們直接看看代理模式在Android中的應用,若是你查看AIDL生成的代碼就知道,它會根據當前的線程判斷是否要跨進程訪問,若是不須要跨進程就直接返回實例,若是須要跨進程則返回一個代理,這個代理幹什麼事情呢?咱們在《 簡單明瞭,完全地理解Binder》提到,在跨進程通訊時,須要把參數寫入到Parcelable對象,而後再執行transact函數,咱們要寫的代碼挺多的。AIDL經過生成一個代理類,代理類中自動幫咱們寫好這些操做。
定義:將對象組成成樹形結構,以表示「部分-總體」的層次結構,使得用戶對單個對象和組合對象的使用具備一致性。
上面的定義不太好理解,咱們直接從Android中用到的組合模式提及。咱們知道,Android中View的結構是樹形結構,每一個ViewGroup包含一系列的View,而ViewGroup自己又是View。這是Android中很是典型的組合模式。
定義:把一個類的接口變換成客戶端所期待的另外一個接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。
其實適配器模式很容易理解,咱們在Android開發時也常常用到。比較典型的有ListView和RecyclerView。爲何ListView須要使用適配器呢?主要是,ListView只關心它的每一個ItemView,而不關心這個ItemView具體顯示的是什麼。而咱們的數據源存放的是要顯示的內容,它保存了每個ItemView要顯示的內容。ListView和數據源之間沒有任何關係,這時候,須要經過適配器,適配器提供getView方法給ListView使用,每次ListView只需提供位置信息給getView函數,而後getView函數根據位置信息向數據源獲取對應的數據,根據數據返回不一樣的View。
定義:動態的給一個對象添加額外的智者,就增長功能來講,裝飾模式比子類繼承的方式更靈活。 經過簡單代碼來理解裝飾模式:
public abstract class Component{
public abstract void operate();
}
public class ConcreteComponent extends Component{
public void operate(){
//具體的實現
}
}
public class Decorator{
private Component component;
public Decorator(Component component){
this.component=component;
}
public void operate(){
operateA();
component.operate();
operateB();
}
public void operateA(){
//具體操做
}
public void operateB(){
//具體操做
}
}
複製代碼
那麼在Android哪裏出現了裝飾模式呢?咱們平時常常用到Context類,可是其實Context類只是個抽象類,具體實現是ContextImpl,那麼誰是ContextImpl的裝飾類呢?咱們知道Activity是個Context,可是Activity 並非繼承於Context,而是繼承於ContextThremeWrapper.而ContextThremeWrapper繼承於ContextWrapper,ContextWrapper繼承Context.說了這麼多,跟裝飾模式有啥關係?主要是引入ContextWrapper這個類。ContextWrapper內部有個Context引用mContext,而且ContextWrapper中對Context的每一個方法都有實現,在實現中調用的就是mContext相同的方法。
定義:使用享元對象有效地支持大量的細粒度對象。
享元模式咱們平時接觸真的不少,好比Java中的常量池,線程池等。主要是爲了重用對象。
在Android哪裏用到了享元模式呢?線程通訊中的Message,每次咱們獲取Message時調用Message.obtain()其實就是從消息池中取出可重複使用的消息,避免產生大量的Message對象。
定義:要求一個子系統的外部與其內部的通訊必須經過一個統一的對象進行。
怎麼理解呢,舉個例子,咱們在啓動計算機時,只需按一下開關鍵,無需關係裏面的磁盤、內存、cpu、電源等等這些如何工做,咱們只關心他們幫我啓動好了就行。實際上,因爲裏面的線路太複雜,咱們也沒辦法去具體瞭解內部電路如何工做。主機提供惟一一個接口「開關鍵」給用戶就好。
那麼Android哪裏使用到了外觀模式呢?依然回到Context,Android內部有不少複雜的功能好比startActivty、sendBroadcast、bindService等等,這些功能內部的實現很是複雜,若是你看了源碼你就能感覺獲得,可是咱們無需關心它內部實現了什麼,咱們只關心它幫咱們啓動Activity,幫咱們發送了一條廣播,綁定了Activity等等就夠了。
定義:將抽象部分與實現部分分離,使他們獨立地進行變化。 其實就是,一個類存在兩個維度的變化,且這兩個維度都須要進行擴展。
在Android中橋接模式用的不少,舉個例子,對於一個View來講,它有兩個維度的變化,一個是它的描述好比Button、TextView等等他們是View的描述維度上的變化,另外一個維度就是將View真正繪製到屏幕上,這跟Display、HardwareLayer和Canvas有關。這兩個維度能夠當作是橋接模式的應用。
MVC模式的意思是,軟件能夠分紅三個部分。
視圖(View):用戶界面。 控制器(Controller):業務邏輯 模型(Model):數據保存 各部分之間的通訊方式以下。
View 傳送指令到 Controller Controller 完成業務邏輯後,要求 Model 改變狀態 Model 將新的數據發送到 View,用戶獲得反饋
全部通訊都是單向的。
MVP 模式將 Controller 更名爲 Presenter,同時改變了通訊方向。
各部分之間的通訊,都是雙向的。
View 與 Model 不發生聯繫,都經過 Presenter 傳遞。
View 很是薄,不部署任何業務邏輯,稱爲"被動視圖"(Passive View),即沒有任何主動性,而 Presenter很是厚,全部邏輯都部署在那裏。
MVVM 模式將 Presenter 更名爲 ViewModel,基本上與 MVP 模式徹底一致。
惟一的區別是,它採用雙向綁定(data-binding):View的變更,自動反映在 ViewModel,反之亦然。Angular 和 Ember 都採用這種模式。