1. 程式人生 > 其它 >設計模式彙總(Android面試)

設計模式彙總(Android面試)

技術標籤:android

設計模式分類

模式 & 描述包括
建立型模式
提供了一種在建立物件的同時隱藏建立邏輯的方式。
工廠模式(Factory Pattern)
抽象工廠模式(Abstract Factory Pattern)
單例模式(Singleton Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
結構型模式
關注類和物件的組合。
介面卡模式(Adapter Pattern)
橋接模式(Bridge Pattern)
過濾器模式(Filter、Criteria Pattern)
組合模式(Composite Pattern)
裝飾器模式(Decorator Pattern)
外觀模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
行為型模式
特別關注物件之間的通訊。
責任鏈模式(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)

面向物件六大原則

原則描述
單一職責原則一個類只負責一個功能領域中的相應職責。
開閉原則物件應該對於擴充套件是開放的,對於修改是封閉的。
里氏替換原則所有引用基類的地方必須能透明地使用其子類的物件。
依賴倒置原則高層模組不依賴低層模組,兩者應該依賴其物件;抽象不應該依賴細節;細節應該依賴抽象。
介面隔離原則類間的依賴關係應該建立在最小的介面上。
迪米特原則也稱最少知識原則,一個物件對其他物件有最少的瞭解。

工廠模式

適用於複雜物件的建立。

示例:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.demo);

BitmapFactory.java

// 生成 Bitmap 物件的工廠類 BitmapFactory
public class BitmapFactory {
    ···
    public static Bitmap decodeFile(String pathName) {
        ···
    }
    ···

    public static Bitmap decodeResource(Resources res, int id, Options opts) {
        validate(opts);
        Bitmap bm = null;
        InputStream is = null; 
        
        try {
            final TypedValue value = new TypedValue();
            is = res.openRawResource(id, value);

            bm = decodeResourceStream(res, value, is, null, opts);
        } 
        ···
        return bm;
    }
    ···
}

單例模式

確保某一個類只有一個例項,並自動例項化向整個系統提供這個例項,且可以避免產生多個物件消耗資源。

示例:

InputMethodManager.java

/**
* Retrieve the global InputMethodManager instance, creating it if it
* doesn't already exist.
* @hide
*/
public static InputMethodManager getInstance() {
    synchronized (InputMethodManager.class) {
        if (sInstance == null) {
            try {
                sInstance = new InputMethodManager(Looper.getMainLooper());
            } catch (ServiceNotFoundException e) {
                throw new IllegalStateException(e);
            }
        }
        return sInstance;
    }
}

建造者模式

將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示,適用於初始化的物件比較複雜且引數較多的情況。

示例:

AlertDialog.Builder builder = new AlertDialog.Builder(this)
        .setTitle("Title")
        .setMessage("Message");
AlertDialog dialog = builder.create();
dialog.show();

AlertDialog.java

public class AlertDialog extends Dialog implements DialogInterface {
    ···

    public static class Builder {
        private final AlertController.AlertParams P;
        ···

        public Builder(Context context) {
            this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
        }
        ···

        public Builder setTitle(CharSequence title) {
            P.mTitle = title;
            return this;
        }
        ···

        public Builder setMessage(CharSequence message) {
            P.mMessage = message;
            return this;
        }
        ···

        public AlertDialog create() {
            // Context has already been wrapped with the appropriate theme.
            final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
            P.apply(dialog.mAlert);
            ···
            return dialog;
        }
        ···
    }
}

原型模式

用原型模式例項指定建立物件的種類,並通過拷貝這些原型建立新的物件。

示例:

ArrayList<T> newArrayList = (ArrayList<T>) arrayList.clone();

ArrayList.java

/**
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
 * elements themselves are not copied.)
 *
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

介面卡模式

介面卡模式把一個類的介面變成客戶端所期待的另一種介面,從而使原因介面不匹配而無法一起工作的兩個類能夠在一起工作。

示例:

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setAdapter(new MyAdapter());

private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ···
    }

    ···
}

RecyclerView.java

···
private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
        boolean removeAndRecycleViews) {
    if (mAdapter != null) {
        mAdapter.unregisterAdapterDataObserver(mObserver);
        mAdapter.onDetachedFromRecyclerView(this);
    }
    ···
    mAdapterHelper.reset();
    final Adapter oldAdapter = mAdapter;
    mAdapter = adapter;
    if (adapter != null) {
        adapter.registerAdapterDataObserver(mObserver);
        adapter.onAttachedToRecyclerView(this);
    }
    if (mLayout != null) {
        mLayout.onAdapterChanged(oldAdapter, mAdapter);
    }
    mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
    mState.mStructureChanged = true;
}

···
public final class Recycler {
    @Nullable
    ViewHolder tryGetViewHolderForPositionByDeadline(int position,
            boolean dryRun, long deadlineNs) {
        ···
        ViewHolder holder = null;
        ···
        if (holder == null) {
            ···
            holder = mAdapter.createViewHolder(RecyclerView.this, type);
            ···
        }
        ···
        return holder;
    }
}

···
public abstract static class Adapter<VH extends ViewHolder> {
    ···
    @NonNull
    public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);

    @NonNull
    public final VH createViewHolder(@NonNull ViewGroup parent, int viewType) {
        try {
            TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
            final VH holder = onCreateViewHolder(parent, viewType);
            ···
            holder.mItemViewType = viewType;
            return holder;
        } finally {
            TraceCompat.endSection();
        }
    }
    ···
}

觀察者模式

定義物件間一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新。

示例:

MyAdapter adapter = new MyAdapter();
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();

RecyclerView.java

···
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();

···
private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
        boolean removeAndRecycleViews) {
    ···
    mAdapter = adapter;
    if (adapter != null) {
        adapter.registerAdapterDataObserver(mObserver);
        adapter.onAttachedToRecyclerView(this);
    }
    ···
}

···
public abstract static class Adapter<VH extends ViewHolder> {
    private final AdapterDataObservable mObservable = new AdapterDataObservable();
    ···
    public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) {
        mObservable.registerObserver(observer);
    }

    ···
    public final void notifyDataSetChanged() {
        mObservable.notifyChanged();
    }
}

static class AdapterDataObservable extends Observable<AdapterDataObserver> {
    ···
    public void notifyChanged() {
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onChanged();
        }
    }
    ···
}

private class RecyclerViewDataObserver extends AdapterDataObserver {
    ···
    @Override
    public void onChanged() {
        assertNotInLayoutOrScroll(null);
        mState.mStructureChanged = true;

        processDataSetCompletelyChanged(true);
        if (!mAdapterHelper.hasPendingUpdates()) {
            requestLayout();
        }
    }
    ···
}

代理模式

為其他的物件提供一種代理以控制對這個物件的訪問。適用於當無法或不想直接訪問某個物件時通過一個代理物件來間接訪問,為了保證客戶端使用的透明性,委託物件與代理物件需要實現相同的介面。

示例:

Context.java

public abstract class Context {
    ···
    public abstract void startActivity(@RequiresPermission Intent intent);
    ···
}

ContextWrapper.java

public class ContextWrapper extends Context {
    Context mBase; // 代理類,實為 ContextImpl 物件
    ···

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
    ···

    @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent); // 核心工作交由給代理類物件 mBase 實現
    }
    ···
}

ContextImpl.java

// Context 的真正實現類
class ContextImpl extends Context {
    ...
    @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
    ...
}

責任鏈模式

使多個物件都有機會處理請求,從而避免了請求的傳送者和接受者之間的耦合。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。

ViewGroup.java

@UiThread
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
    ···
    private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
            View child, int desiredPointerIdBits) {
        final boolean handled;
        ···
        final MotionEvent transformedEvent;
        if (newPointerIdBits == oldPointerIdBits) {
            if (child == null || child.hasIdentityMatrix()) {
                if (child == null) {
                    handled = super.dispatchTouchEvent(event);
                } else {
                    ···
                    // 獲取子 view 處理的結果
                    handled = child.dispatchTouchEvent(event);
                }
                return handled;
            }
            transformedEvent = MotionEvent.obtain(event);
        } else {
            transformedEvent = event.split(newPointerIdBits);
        }

        // Perform any necessary transformations and dispatch.
        if (child == null) {
            handled = super.dispatchTouchEvent(transformedEvent);
        } else {
            ···
            // 獲取子 view 處理的結果
            handled = child.dispatchTouchEvent(transformedEvent);
        }
        ···
        return handled;
    }
    ···
}

策略模式

策略模式定義了一系列的演算法,並封裝起來,提供針對同一型別問題的多種處理方式。

示例:

// 勻速
animation.setInterpolator(new LinearInterpolator());
// 加速
animation.setInterpolator(new AccelerateInterpolator());
···

BaseInterpolator.java

/**
 * An abstract class which is extended by default interpolators.
 */
abstract public class BaseInterpolator implements Interpolator {
    private @Config int mChangingConfiguration;
    /**
     * @hide
     */
    public @Config int getChangingConfiguration() {
        return mChangingConfiguration;
    }

    /**
     * @hide
     */
    void setChangingConfiguration(@Config int changingConfiguration) {
        mChangingConfiguration = changingConfiguration;
    }
}

LinearInterpolator.java

@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    ···
}

AccelerateInterpolator.java

@HasNativeInterpolator
public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    ···
}

備忘錄模式

在不破壞封閉的前提下,在物件之外儲存儲存物件的當前狀態,並且在之後可以恢復到此狀態。

示例:

Activity.java

// 儲存狀態
protected void onSaveInstanceState(Bundle outState) {
    // 儲存當前視窗的檢視樹的狀態
    outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

    outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
    // 儲存 Fragment 的狀態
    Parcelable p = mFragments.saveAllState();
    if (p != null) {
        outState.putParcelable(FRAGMENTS_TAG, p);
    }
    if (mAutoFillResetNeeded) {
        outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
        getAutofillManager().onSaveInstanceState(outState);
    }
    // 呼叫 ActivityLifecycleCallbacks 的 onSaveInstanceState 進行儲存狀態
    getApplication().dispatchActivitySaveInstanceState(this, outState);
}

···
// onCreate 方法中恢復狀態
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ···
    if (savedInstanceState != null) {
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
        mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                View.LAST_APP_AUTOFILL_ID);

        if (mAutoFillResetNeeded) {
            getAutofillManager().onCreate(savedInstanceState);
        }

        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.fragments : null);
    }
    mFragments.dispatchCreate();
    getApplication().dispatchActivityCreated(this, savedInstanceState);
    ···
    mRestoredFromBundle = savedInstanceState != null;
    mCalled = true;
}

ActivityThread.java

@Override
public void handleStartActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions) {
    final Activity activity = r.activity;
    ···
    // Start
    activity.performStart("handleStartActivity");
    r.setState(ON_START);
    ···
    // Restore instance state
    if (pendingActions.shouldRestoreInstanceState()) {
        if (r.isPersistable()) {
            if (r.state != null || r.persistentState != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                        r.persistentState);
            }
        } else if (r.state != null) {
            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
        }
    }
    ···
}