1. 程式人生 > >23種設計模式在Android中的應用

23種設計模式在Android中的應用

ets ros 而不是 auto 排隊 private eth mail 記錄

所有江湖偶遇,都是宿命相逢 ----《逆水寒》,只是覺得文案不錯,就用了。哈哈!

一.設計原則:

單一職責原則(SRP):任何一個對象都應給只有一個單獨的職責(“低耦合,高內聚”)
裏氏替換原則(LSP):在任何父類出現的地方都可以用子類替換
依賴註入原則(DIP):要依賴於抽象而不是依賴於具體實現(此原則是開閉原則的基礎)
接口分離原則(ISP):不應該強迫他們的客戶程序依賴他們不需要的方法
迪米特原則(LOD):一個對象應該對其他對象盡可能少的了解,意思就是降低各個對象之間的耦合。
開閉原則(OCP):一個對對象對擴展是開放的,對修改是關閉的。

二.23中設計模式

1.工廠模式(Factory Pattern):

在工廠模式中,客戶類與工廠來是分開的,消費者任何時候需要產品只需要向工廠請求就好,消費者無需修改就可以接納新產品。缺點是:當前產品修改是工廠也需要修改。

2.建造模式(Builder Pattern):將產品的內部表象和產品的生成過程分割開來,從而使一個建造過程生成具有不同表象的產品,建造模式使得產品內部表象可以獨立的變化,客戶不必知道產品的內部細節。建造模式可以強制實行一種分步驟的建造過程。

技術分享圖片
AlertDialog.Builder builder  = new AlertDialog.Builder(this);
        builder.setTitle("")
                .setIcon(R.drawable.ic_launcher_foreground)
                .setView(R.layout.activity_main)
                .setOnKeyListener(
new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) { return false; } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override
public void onCancel(DialogInterface dialogInterface) { } }) .create().show();
View Code

3.工廠方法模式(Abstract Factory Pattern):在工廠方法模式中,核心工廠類不再負責所有的產品的創建,而是將具體創建工作交給子類處理,成為一個抽象角色,僅負責給出具體工廠必須實現的接口,而不接觸某款產品的實例化細節。

4.原型模型模式(Prototype Pattern):原型模型是通過給定一個原型對象來指明要創建的的對象類型,可以用復制這個對象的方法創建更多的對象,原型模型允許動態的增加或減少產品類。缺點是:每一個類必須配備一個克隆方法。

5.單例模式(Singleton Pattern):確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例單例模式。

- 餓漢式單例

public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}

-懶漢式單例

/**
* Singleton helper class for lazily initialization.
*
* Modeled after frameworks/base/include/utils/Singleton.h
*
* @hide
*/
public abstract class Singleton<T> {
private T mInstance;

protected abstract T create();

public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}

  餓漢模式是在系統運行起來,在裝在類的時候就進行初始化的操作,外部對象使用的時候不需要做任何判斷可以直接使用,從效率上來說是優於懶漢模式的.但是對比懶漢模式的延遲加載技術,不管系統用不用該實例,內存都會在最開始的時候創建出來.跟懶漢的時間換空間正好相反,餓漢是空間換時間。

6.適配器模式(Adapter Pattern):把我一個類的接口變化成客戶端期望的另一個接口。

Adapter.java Android8.0源碼

技術分享圖片
/**
 * adapter 對象充當 AdapterView 和該View展現數據的橋梁。提供對數據的訪問。
 * 還負責每一個 android.view.View 控件的數據集控制。
 * @see android.widget.ArrayAdapter
 * @see android.widget.CursorAdapter
 * @see android.widget.SimpleCursorAdapter
 */
public interface Adapter {
    /**
     * Register an observer that is called when changes happen to the data used by this adapter.
     * 當這個適配器使用的數據放生變化時候,註冊一個觀察者
     * @param observer the object that gets notified when the data set changes.
     * @param observer 當數據集發生變化,得到通知的對象
     */
    void registerDataSetObserver(DataSetObserver observer);

    /**
     * Unregister an observer that has previously been registered with this
     * adapter via {@link #registerDataSetObserver}.
     * 該方法是註銷觀察者作用,
     * @param observer the object to unregister.
     * @param observer 需要註銷的觀察者
     */
    void unregisterDataSetObserver(DataSetObserver observer);

    /**
     * How many items are in the data set represented by this Adapter.
     * adapter數據集大小
     * @return Count of items.
     * @return 返回數據集大小
     */
    int getCount();   
    
    /**
     * Get the data item associated with the specified position in the data set.
     * 返回數據集對應索引(position)的數據項對象
     * @param position Position of the item whose data we want within the adapter‘s 
     * data set.
     * @return The data at the specified position.
     */
    Object getItem(int position);
    
    /**
     * Get the row id associated with the specified position in the list.
     * 返回數據集對應索引(position)的數據項Id
     * @param position The position of the item within the adapter‘s data set whose row id we want.
     * @return The id of the item at the specified position.
     */
    long getItemId(int position);
    
    /**
     * Indicates whether the item ids are stable across changes to the
     * underlying data.
     * 如果相同的ID總是引用相同的對象,則為true。
     * @return True if the same id always refers to the same object.
     */
    boolean hasStableIds();
    
    /**
     * Get a View that displays the data at the specified position in the data set. You can either
     * create a View manually or inflate it from an XML layout file. When the View is inflated, the
     * parent View (GridView, ListView...) will apply default layout parameters unless you use
     * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
     * to specify a root view and to prevent attachment to the root.
     * 返回數據集中對應索引(position)指定的View。同樣也可以創建一個視圖或者通過xml布局inflate。
     * 如果是通過inflate獲取視圖時候,@param parent 可以是GridView 或者ListView等控件。
     * 除非你用{@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}指定根視圖並防止附著,否則使用默認的布局參數。
     * @param position The position of the item within the adapter‘s data set of the item whose view
     *        we want.
     * @param position 我們想要返回的視圖,對應數據集索引(position)
     * @param convertView The old view to reuse, if possible. Note: You should check that this view
     *        is non-null and of an appropriate type before using. If it is not possible to convert
     *        this view to display the correct data, this method can create a new view.
     *        Heterogeneous lists can specify their number of view types, so that this View is
     *        always of the right type (see {@link #getViewTypeCount()} and
     *        {@link #getItemViewType(int)}).
     * @param convertView 如果可以,重用舊視圖。註意:需要檢查視圖不是null並且是適當的類型。如果不能重用,可以創建一個視圖。
     * @param parent The parent that this view will eventually be attached to
     * @param parent 根視圖
     * @return A View corresponding to the data at the specified position.
     * 返回呈現數據集索引對應數據項的視圖。
     */
    View getView(int position, View convertView, ViewGroup parent);

    /**
     * An item view type that causes the {@link AdapterView} to ignore the item
     * view. For example, this can be used if the client does not want a
     * particular view to be given for conversion in
     * {@link #getView(int, View, ViewGroup)}.
     * 
     * @see #getItemViewType(int)
     * @see #getViewTypeCount()
     */
    static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;
    
    /**
     * Get the type of View that will be created by {@link #getView} for the specified item.
     * 
     * @param position The position of the item within the adapter‘s data set whose view type we
     *        want.
     * @return An integer representing the type of View. Two views should share the same type if one
     *         can be converted to the other in {@link #getView}. Note: Integers must be in the
     *         range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can
     *         also be returned.
     * @see #IGNORE_ITEM_VIEW_TYPE
     */
    int getItemViewType(int position);
    
    /**
     * <p>
     * Returns the number of types of Views that will be created by
     * {@link #getView}. Each type represents a set of views that can be
     * converted in {@link #getView}. If the adapter always returns the same
     * type of View for all items, this method should return 1.
     * </p>
     * <p>
     * This method will only be called when the adapter is set on the {@link AdapterView}.
     * </p>
     * 
     * @return The number of types of Views that will be created by this adapter
     */
    int getViewTypeCount();
    
    static final int NO_SELECTION = Integer.MIN_VALUE;
 
     /**
      * @return true if this adapter doesn‘t contain any data.  This is used to determine
      * whether the empty view should be displayed.  A typical implementation will return
      * getCount() == 0 but since getCount() includes the headers and footers, specialized
      * adapters might want a different behavior.
      */
     boolean isEmpty();

    /**
     * Gets a string representation of the adapter data that can help
     * {@link android.service.autofill.AutofillService} autofill the view backed by the adapter.
     *
     * <p>
     * It should only be set (i.e., non-{@code null} if the values do not represent PII
     * (Personally Identifiable Information - sensitive data such as email addresses,
     * credit card numbers, passwords, etc...). For
     * example, it‘s ok to return a list of month names, but not a list of usernames. A good rule of
     * thumb is that if the adapter data comes from static resources, such data is not PII - see
     * {@link android.view.ViewStructure#setDataIsSensitive(boolean)} for more info.
     *
     * @return {@code null} by default, unless implementations override it.
     */
    default @Nullable CharSequence[] getAutofillOptions() {
        return null;
    }
}
View Code

7.橋接模式(Bridge Pattern):將抽象化和實現化脫耦,使得二者可以獨立變化,也就是說,將他們的強關聯變成弱關聯,即軟件系統使用的是組合/聚合關系而不是繼承關系,從而使兩者可以獨立變化。

8.合成模式(Composite Pattern):將對象組合成樹形結構以表示“部分-整體”的層次結構,使得用戶對單個對象和組合對象的使用具有一致性

9.裝飾者模式(Decorator Pattern):裝飾者模式以客戶端透明的方式擴展對象的功能,是繼承方案的一個替代方案,提供了比繼承更多的靈活性,動態的的給一個對象添加功能,這些功能又可以動態的撤銷。可增加又一些基本功能排列組合產生非常強大的功能。

10.門面模式(Facade Pattern):外部與一個子系統通信必須通過一個門面對象進行,門面模式提供一個高層次的接口,使得子系統更容易使用。每一個子系統只有一個門面類,而且此門面類只有一個實例,單整個系統可以有多個門面類。

11.享元模式(Flyweight Pattern):使用共享對象可有效地支持大量的細粒度對象。

12.代理模式(Proxy pattern):給某一個對象創建一個代理對象,並由代理對象控制源對象的應用。

13.責任鏈模式(chain of responsinbleity Pattern):使多個對象有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關系 。將這些對象連成一個鏈,並沿著這條鏈傳遞請求,知道有對象處理它為止

14.命令模式(cmd Pattern):將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。

15.解釋器模式(Interpreter Pattern):給定一門語言,定義它的文法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。

16.叠代子模式(Iterator Pattern):它提供一種方法訪問一個容器對象中各個元素,而又不需要暴露該對象的內部細節。

17.調停者模式(mediator Pattern ):調停者模式包裝了一系列對象相互作用的方式,使得這些對象不必相互明顯作用。從而使他們可以松散偶合。當某些對象之間的作用發生改變時,不會立即影響其他的一些對象之間的作用。保證這些作用可以彼此獨立的變化。調停者模式將多對多的相互作用轉化為一對多的相互作用。調停者模式將對象的行為和協作抽象化,把對象在小尺度的行為上與其他對象的相互作用分開處理。

18.備忘錄模式(Memento Pattern):在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,這樣以後就可將該對象恢復到原來保存的狀態。

19.觀察者模式(Observer Pattern):定義對象間一種一對多的依賴關系,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新

20.狀態模式(state Pattern ):當一個對象在狀態改變時允許其改變行為,這個對象看起來像改變了其類。

21.策略模式(Strategy Pattern):定義一組算法,將每個算法都封裝起來,並且使他們之間可以互換

22.模板方法模式(Template Method Pattern):

23.訪問者模式(Visitor Pattern):封裝一些作用於某種數據結構中的各種元素,它可以在不改變數據結構的前提下定義作用於這些元素的新的操作


參考:
https://blog.csdn.net/forwujinwei/article/details/79050044

23種設計模式在Android中的應用