国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android:四大架構的優缺點,你真的了解嗎?

big_cat / 2329人閱讀

摘要:架構的特點與局限架構的特點是面向接口編程。架構的特點和不足為解決職能邊界不明確的問題,在架構中,業務邏輯的職能被轉移到領域層,由專職管理。的作用是視覺交互,為此的職責范圍是請求數據和處理邏輯。

聲明轉載于作者:KunMinX
原文鏈接:https://www.jianshu.com/p/9ef...

前言

前不久剛結束對 20 模塊項目的第 3 輪重構,一路見證 MVC、MVP、Clean 的優缺點并形成自己的體會。

近期在總結工作經驗的同時,開始寫博客。順便開源了我設計的 ViaBus 架構。

項目地址:
https://github.com/KunMinX/an...
項目常用架構比對

以下,對常見的 MVC、MVP、Clean、AAC 架構做個比對。

首先,一張表格展示各架構的類冗余情況:

需求是,寫三個頁面,ListFragment、DetailFragment、PreviewFragment,每個頁面至少用到 3個 Note 業務、3個 User 業務。問:上述架構分別需編寫多少類?

架構 涉及類 類總數
MVC Fragment:3個,Controller:3個,Model:2個 8個
MVP Fragment:3個,Presenter:3個,Model:3個,Contract:1個 10個
Clean Fragment:3個,ViewModel:3個,Usecase:18個,Model:3個 27個
AAC Fragment:3個,ViewModel:3個,Model:3個 9個
MVC 架構的缺陷

View、Controller、Model 相互依賴,造成代碼耦合。

難以分工,難以將 View、Controller、Model 分給不同的人寫。

難以維護,沒有中間件接口做緩沖,難以替換底層的實現。

public class NoteListFragment extends BaseFragment {

    ...

    public void refreshList() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                //view 中直接依賴 model。那么 view 須等 model 編寫好才能開工。

                mNoteList = mDataManager.getNoteList();
                mHandler.sendMessage(REFRESH_LIST, mNoteList);
            }
        }).start();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg) {
                case REFRESH_LIST:
                    mAdapter.setList(mNoteList);
                    mAdapter.notifyDataSetChanged();
                    break;
                default:
            }
        }
    };

    ...
}
MVP 架構的特點與局限

MVP 架構的特點是 面向接口編程。在 View、Presenter、Model 之間分別用 中間件接口 做銜接,當有新的底層實現時,能夠無縫替換。

此外,MVP 的 View 和 Model 并不產生依賴,因此可以說是對 View 和 Model 做了代碼解耦。

public class NoteListContract {

    interface INoteListView {

        void showDialog(String msg);

        void showTip(String tip);

        void refreshList(List beans);
    }

    interface INoteListPresenter {

        void requestNotes(String type);

        void updateNotes(NoteBean... beans);

        void deleteNotes(NoteBean... beans);
    }

    interface INoteListModel {

        List getNoteList();

        int updateNote(NoteBean bean);

        int deleteNote(NoteBean bean);
    }
}

但 MVP 架構有其局限性。按我的理解,MVP 設計的初衷是, “讓天下沒有難替換的 View 和 Model” 。該初衷背后所基于的假設是,“上層邏輯穩定,但底層實現更替頻繁” 。在這個假設的引導下,使得三者中, 只有 Presenter 具備獨立意志和決定權,掌管著 UI 邏輯和業務邏輯,而 View 和 Model 只是外接的工具。

public class NoteListPresenter implements NoteListContract.INoteListPresenter {

    private NoteListContract.INoteListModel mDataManager;
    private NoteListContract.INoteListView mView;

    @Override
    public void requestNotes(String type) {
        Observable.create(new ObservableOnSubscribe>() {
            @Override
            public void subscribe(ObservableEmitter> e) throws Exception {
                List noteBeans = mDataManager.getNoteList();
                e.onNext(noteBeans);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer>() {
                    @Override
                    public void accept(List beans) throws Exception {

                        //presenter 直接干預了 UI 在拿到數據后做什么,使得邏輯上沒有發生解耦。

                        //正常來說,解耦意味著,presenter 的職能邊界僅限返回結果數據,
                        //由 UI 來依據響應碼處理 UI 邏輯。

                        mView.refreshList(beans);
                    }
                });
    }

    ...
}

然而,這樣的假設多數時候并不實際。可視化需求是變化多端的,在牽涉到視覺交互時,必然涉及 UI 邏輯的修改,也就是說,View 和 Presenter 的相互牽連,使得 UI 的改動需要 View 和 Presenter 編寫者配合著完成,增加溝通協作成本。

長久來看,二者都難以成長。Presenter 編寫者容易被各種非本職工作拖累,View 的編寫者不會嘗試獨立自主,例如通過多態等模式將 UI 封裝成可適應性的組件,反正 ... 有 Presenter 來各種 if else 嘛。

Clean 架構的特點和不足

為解決 Presenter 職能邊界不明確 的問題,在 Clean 架構中,業務邏輯的職能被轉移到領域層,由 Usecase 專職管理。Presenter 則弱化為 ViewModel ,作為代理數據請求,和銜接數據回調的緩沖區。

Clean 架構的特點是 單向依賴、數據驅動編程。 View -> ViewModel -> Usecase -> Model

View 對 ViewModel 的單向依賴,是通過 databinding 特性實現的。ViewModel 只負責代理數據請求,在 Usecase 處理完業務返回結果數據時,結果數據被賦值給可觀察的 databinding 數據,而 View 則依據數據的變化而變化。

public class NoteListViewModel {

    private ObservableList mListObservable = new ObservableArrayList<>();

    private void requestNotes(String type) {
        if (null == mRequestNotesUsecase) {
            mRequestNotesUsecase = new ProveListInitUseCase();
        }

        mUseCaseHandler.execute(mRequestNotesUsecase, new RequestNotesUsecase.RequestValues(type),
                new UseCase.UseCaseCallback() {
                    @Override
                    public void onSuccess(RequestNotesUsecase.ResponseValue response) {

                        //viewModel 的可觀察數據發生變化后,databinding 會自動更新 UI 展示。

                        mListObservable.clear();
                        mListObservable.addAll(response.getNotes());
                    }

                    @Override
                    public void onError() {

                    }
                });
    }

    ...
}

但 Clean 架構也有不足:粒度太細 。一個 Usecase 受限于請求參數,因而只能處理一類請求。View 請求的數據包含幾種類型,就至少需要準備幾個 Usecase。Usecase 是依據當前 View 對數據的需求量身定制的,因此 Usecase 的復用率極低,項目會因而急劇的增加類和重復代碼。

public class RequestNotesUseCase extends UseCase {

    private DataManager mDataManager;

    @Override
    protected void executeUseCase(final RequestValues values) {
        List noteBeans = mDataManager.getNotes();
        ...
        getUseCaseCallback().onSuccess(new RequestNotesUseCase.ResponseValue(noteBeans));
    }

    //每新建一個 usecase 類,都需要手動為其配置 請求參數列表 和 響應參數列表。

    public static final class RequestValues implements UseCase.RequestValues {
        private String type;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

    public static final class ResponseValue implements UseCase.ResponseValue {

        public List mBeans;

        public ResponseValue(List beans) {
            mBeans = beans;
        }
    }
}
AAC 架構的特點

AAC 也是數據驅動編程。只不過它不依賴于 MVVM 特性,而是直接在 View 中寫個觀察者回調,以接收結果數據并處理 UI 邏輯。

public class NoteListFragment extends BaseFragment {

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        viewModel.getNote().observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable NoteBean bean) {
                //update UI
            }
        });
    }

    ...
}

你完全可以將其理解為 B/S 架構:從 Web 前端向 Web 后端發送了數據請求,后端在處理完畢后響應結果數據給前端,前端再依據需求處理 UI 邏輯。等于說, AAC 將業務完全壓到了 Model 層。

ViaBus 架構的由來及特點

上一輪重構項目在用 Clean 架構,為此我決定跳過 AAC,基于對移動端數據交互的理解,編寫“消息驅動編程”架構。

由于借助總線來代理數據的請求和響應,因此取名 ViaBus。

不同于以往的架構,ViaBus 明確界定了什么是 UI,什么是業務。

UI 的作用是視覺交互,為此 UI 的職責范圍是請求數據和處理 UI 邏輯 。業務的作用是供應數據,因此 業務的職責范圍是接收請求、處理數據、返回結果數據 。

UI 不需要知道數據是怎么來的、通過誰來的,它只需向 bus 發送一個請求,如果有業務注冊了該類 “請求處理者”,那么自然有人來處理。業務也無需知道 UI 在拿到數據后會怎么用,它只需向 bus 回傳結果,如果有 UI 注冊了“觀察響應者”,那么自然有人接收,并依據響應碼行事。

這樣,在靜態 bus 的加持下,UI 和業務是完全解耦的,從根本上解決了相互牽連的問題。此外,不同于上述架構的每個 View 都要對應一個 Presenter 或 ViewModel,在 ViaBus 中,一個模塊中的 UI 可以共享多個“業務處理者”實例,使 代碼的復用率提升到100%。

閱讀更多

APP瘦身這一篇就夠了

一招教你打造一個滑動置頂的視覺特效

Android組件化demo實現以及遇坑分享

(Android)面試題級答案(精選版)

歡迎關注我微信公眾號:終端研發部 ,如果您有什么問題可以一塊學習和交流

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/11933.html

相關文章

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<