《Android源碼設計模式解析與實戰》讀書筆記之第五章 —— 工廠方法模式

目錄

1. 工廠方法模式的定義

2. 工廠方法模式的使用場景

3. UML圖與示例代碼

4. 工廠方法模式在Android中的應用


1. 工廠方法模式的定義

定義一個用於創建對象的接口,讓子類決定實例化哪個類。

2. 工廠方法模式的使用場景

需要生成複雜對象時,都可以使用工廠方法模式,用new就可以完成的不用使用工廠方法模式。

3. UML圖與示例代碼

工廠方法模式

實例代碼

abstract class Product {
    public abstract void method();
}

class ConcreteProductA extends Product {
    @Override
    public void method() {
        System.out.println("我是具體產品A");
    }
}

class ConcreteProductB extends Product {
    @Override
    public void method() {
        System.out.println("我是具體產品B");
    }
}

abstract class Factory {
    abstract Product createProduct();
}

class ConcreteFactory extends Factory {

    /**
     * 創建具體對象,想創建哪個就返回哪個,也可以採用字符串區分,
     * 不過這樣寫明顯不靈活
     */
    @Override
    Product createProduct() {
//        return new ConcreteProductA();
        return new ConcreteProductB();
    }
}

public class FactoryTest {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct();
        product.method();
    }
}

所以也可以採用反射的方式:

abstract class Factory {
    // 表示返回值是T或者T的子類
    abstract <T extends Product>T createProduct(Class<T> tClass) throws ClassNotFoundException, IllegalAccessException, InstantiationException;
}

class ConcreteFactory extends Factory {
    @Override
    <T extends Product> T createProduct(Class<T> tClass) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Product product = null;
        product = (Product) Class.forName(tClass.getName()).newInstance();
        return (T)product;
    }
}

public class FactoryTest {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct(ConcreteProductB.class);
        product.method();
    }
}

上面註釋中提到,如果只用一個工廠創建所有的產品類,這樣的設計不夠靈活,一旦產品多起來,就要不斷修改工廠類的create方法,這樣不符合第一章提到的開閉原則。因此,我們可以爲每個產品類設計一個屬於它的具體工廠。

class ConcreteFactoryA extends Factory {
    @Override
    Product createProduct() {
        return new ConcreteProductA();
    }
}

class ConcreteFactoryB extends Factory {
    @Override
    Product createProduct() {
        return new ConcreteProductB();
    }
}

這樣就擁有了多個工廠,稱爲工廠方法模式

書中還提到了一個小技巧,如果工廠只有一個,那麼可以不用創建抽象的工廠,直接在create方法加上靜態修飾符

 class Factory {
    // 表示返回值是T或者T的子類
    public static Product createProduct() {
        return new ConcreteProductA();
    }
}

4. 工廠方法模式在Android中的應用

Java中的集合

public interface Collection<E> extends Iterable<E> {
    ......
    Iterator<E> iterator();
}
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
    ......
    public Iterator<E> iterator() {
        return new ArrayList.Itr();
    }
}
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable {    
    ......    
    public Iterator<E> iterator() {
        return this.map.keySet().iterator();
    }
}

HashSet和ArrayList最終都間接實現了Collection接口,並負責創建各自的迭代器對象,這就用到了工廠方法模式,具體的創建對象過程由具體類實現。

關於onCreate方法

關於這個問題,我頗有感想,因爲很多剛學習安卓的同學會認爲這個方法相當於程序的入口,其實不是的,這個方法只不過是生命週期其中的一個回調方法,只不過該方法多用於初始化UI等資源,顯得格外重要,但它終究只是生命週期的一個方法。應用程序的入口其實是ActivityThread的main方法。

public final class ActivityThread {
    // Android 4.4 version
    public static void main(String[] args) {
        SamplingProfilerIntegration.start();
        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());
        Security.addProvider(new AndroidKeyStoreProvider());
        Process.setArgV0("<pre-initialized>");
        /* SPRD: in zygote process, Log.ilogStatus may be modified, make sure ilog status is original @{ */
        Log.initIlogStatus();
        /* @} */
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        AsyncTask.init();
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        // 開啓消息循環
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

ActivityThread類是final的,不能夠被繼承的,每一個應用程序對應一個ActivityThread,所以說AT的main方法是應用程序的入口,當Zygote進程孵化出一個新的應用進程後,執行main方法,main方法中幫我們實現了一些資源的初始化,比如AsyncTask、Looper循環的開啓,然後調用attach將其綁定到ActivityManagerService中,開始讀取消息並且分發消息(安卓系統爲事件驅動型系統)

ActivityThread.attach方法

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ......
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                // 調用AMS的attachApplication
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } else {
            ......
        }
    }

將ActivityThread綁定至AMS

ActivityManagerService.attachApplication方法

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

調用ActivityManagerService.attachApplication(ActivityManagerNative.getDefault()返回AMS的實例),在attachApplication中調用attachApplicationLocked進行綁定

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        try {
        thread.bindApplication(processName, appInfo, providers,
                    app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                    app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), 
                    app.compat,getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
        } catch(Exception e) {
            return false;
        }
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                badApp = true;
            }
        }
    return true;
}

attachApplicationLocked的主要作用是,把ApplicationThread對象綁定到ActivityManagerService關鍵在於mStackSupervisor.attachApplicationLocked(app, mHeadless)

ActivityStackSupervisor.attachApplicationLocked

    boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
        ......
                        } else if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
        ......
    }

保留真正實現功能的地方,realStartActivityLocked方法,顧名思義,“真正”啓動Activity

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {

        r.startFreezingScreenLocked(app, 0);
        // 向WindowManager設置Token,標識當前App要在前臺顯示
        mWindowManager.setAppVisibility(r.appToken, true);

        // 蒐集啓動較慢的App的信息
        r.startLaunchTickingLocked();

        // 檢查配置信息
        if (checkConfig) {
            Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    mService.mConfiguration,
                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
            mService.updateConfigurationLocked(config, r, false, false);
        }

        // 設置相關參數信息
        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();
        if (IS_DEBUG_OPTIMIZING) Slog.v(TAG, r.processName + " Activity_START: " + r.lastLaunchTime + " CpuTime: " + android.os.Debug.threadCpuTimeNanos());
        if (localLOGV) Slog.v(TAG, "Launching: " + r);

        int idx = app.activities.indexOf(r);
        if (idx < 0) {
            app.activities.add(r);
        }
        mService.updateLruProcessLocked(app, true, null);
        mService.updateOomAdjLocked();

        final ActivityStack stack = r.task.stack;
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<Intent> newIntents = null;
            if (andResume) {
                results = r.results;
                newIntents = r.newIntents;
            }
            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
                    + " icicle=" + r.icicle
                    + " with results=" + results + " newIntents=" + newIntents
                    + " andResume=" + andResume);
            if (andResume) {
                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
                        r.userId, System.identityHashCode(r),
                        r.task.taskId, r.shortComponentName);
            }
            // 是否是桌面Activity,是的話將其添加到當前Activity棧的底部
            if (r.isHomeActivity() && r.isNotResolverActivity()) {
                // Home process is the root process of the task.
                mService.mHomeProcess = r.task.mActivities.get(0).app;
            }
            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
            r.sleeping = false;
            r.forceNewConfig = false;
            mService.showAskCompatModeDialogLocked(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
            String profileFile = null;
            ParcelFileDescriptor profileFd = null;
            boolean profileAutoStop = false;
            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                if (mService.mProfileProc == null || mService.mProfileProc == app) {
                    mService.mProfileProc = app;
                    profileFile = mService.mProfileFile;
                    profileFd = mService.mProfileFd;
                    profileAutoStop = mService.mAutoStopProfiler;
                }
            }
            app.hasShownUi = true;
            app.pendingUiClean = true;
            if (profileFd != null) {
                try {
                    profileFd = profileFd.dup();
                } catch (IOException e) {
                    if (profileFd != null) {
                        try {
                            profileFd.close();
                        } catch (IOException o) {
                        }
                        profileFd = null;
                    }
                }
            }
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
            // 所有參數信息到位後,準備啓動Activity
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration), r.compat,
                    app.repProcState, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);

            if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
                // This may be a heavy-weight process!  Note that the package
                // manager will ensure that only activity can run in the main
                // process of the .apk, which is the only thing that will be
                // considered heavy-weight.
                if (app.processName.equals(app.info.packageName)) {
                    if (mService.mHeavyWeightProcess != null
                            && mService.mHeavyWeightProcess != app) {
                        Slog.w(TAG, "Starting new heavy weight process " + app
                                + " when already running "
                                + mService.mHeavyWeightProcess);
                    }
                    mService.mHeavyWeightProcess = app;
                    Message msg = mService.mHandler.obtainMessage(
                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                    msg.obj = r;
                    mService.mHandler.sendMessage(msg);
                }
            }

        } catch (RemoteException e) {
            if (r.launchFailed) {
                // This is the second time we failed -- finish activity
                // and give up.
                Slog.e(TAG, "Second failure launching "
                      + r.intent.getComponent().flattenToShortString()
                      + ", giving up", e);
                mService.appDiedLocked(app, app.pid, app.thread);
                stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                        "2nd-crash", false);
                return false;
            }

            // This is the first time we failed -- restart process and
            // retry.
            app.activities.remove(r);
            throw e;
        }

        r.launchFailed = false;
        if (stack.updateLRUListLocked(r)) {
            Slog.w(TAG, "Activity " + r
                  + " being launched, but already in LRU list");
        }

        if (andResume) {
            // As part of the process of launching, ActivityThread also performs
            // a resume.
            stack.minimalResumeActivityLocked(r);
        } else {
            // This activity is not starting in the resumed state... which
            // should look like we asked it to pause+stop (but remain visible),
            // and it has done so and reported back the current icicle and
            // other state.
            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
                    + " (starting in stopped state)");
            r.state = ActivityState.STOPPED;
            r.stopped = true;
        }

        // Launch the new version setup screen if needed.  We do this -after-
        // launching the initial activity (that is, home), so that it can have
        // a chance to initialize itself while in the background, making the
        // switch back to it faster and look better.
        if (isFrontStack(stack)) {
            mService.startSetupActivityLocked();
        }

        return true;
    }

app.thread.scheduleLaunchActivity()調用了ApplicationThread的scheduleLaunchActivity()

public final class ActivityThread {
    private class ApplicationThread extends ApplicationThreadNative {
            // 第二個參數是Binder
            public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                int procState, Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profileFile = profileName;
            r.profileFd = profileFd;
            r.autoStopProfiler = autoStopProfiler;

            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

    }
}

ApplicationThread的scheduleLaunchActivity(),創建一個ActivityClientRecord對象,設置相關參數,然後通過sendMessage方法將ActivityClinetRecord對象發送到消息隊列,由ActivityThread的Handler處理啓動(H.LAUNCH_ACTIVITY標誌)

ActivityThread.H

    private class H extends Handler {
        public static final int LAUNCH_ACTIVITY = 100;
        public void handleMessage(Message msg) {
            ......
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ......
            }
        }
    }

ActivityThread.handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    Activity a = performLaunchActivity(r, customIntent);
}

ActivityThread.performLaunchActivity

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        // 獲取PackageInfo
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        // 獲取ComponentName
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        // 構造Activity對象並設置參數
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            // 獲取Application對象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (activity != null) {
                // 將Application對象、Context對象綁定到Activity對象
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

                if(r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
            }
        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
              ...  
        }

        return activity;
    }

Instrumentation.callActivityOnCreate

public class Instrumentation {
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        if (mWaitingActivities != null) {
            synchronized (mSync) {
                final int N = mWaitingActivities.size();
                for (int i=0; i<N; i++) {
                    final ActivityWaiter aw = mWaitingActivities.get(i);
                    final Intent intent = aw.intent;
                    if (intent.filterEquals(activity.getIntent())) {
                        aw.activity = activity;
                        mMessageQueue.addIdleHandler(new ActivityGoing(aw));
                    }
                }
            }
        }
        
        // 啓動activity
        activity.performCreate(icicle);
        
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }
}

Activity.performCreate

    final void performCreate(Bundle icicle) {
    	bringUpThreadPriority();
        // onCreate被調用
        onCreate(icicle);
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
    }

工廠方法模式實戰

針對不同體量的文件有不同的存儲方式,比如SharePreference、文件、SQLite數據庫等,但他們都有一個共同點,可以進行增刪改查工作,所以針對這點可以抽象出一個類IOHandler

public abstract class IOHandler {
    /**
     * @param id 身份證信息
     * @param name 用戶姓名
     */
    public abstract void add(String id, String name);
    public abstract void remove(String id);
    public abstract void update(String id, String name);
    public abstract String query(String id);

}

SQLite類,繼承自IOHandler

public class SQLiteHandler extends IOHandler {
    @Override
    public void add(String id, String name) {

    }

    @Override
    public void remove(String id) {

    }

    @Override
    public void update(String id, String name) {

    }

    @Override
    public String query(String id) {
        return null;
    }
}

創建各種類型IOHandler的工廠

public class HandlerFactory {
    public static <T extends IOHandler> T createIOHandler(Class<T> tClass) {
        IOHandler ioHandler = null;
        try {
            ioHandler = (IOHandler) Class.forName(tClass.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) ioHandler;
    }
}

客戶端

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SQLiteHandler ioHandler = HandlerFactory.createIOHandler(SQLiteHandler.class);
        ioHandler.add();
        ioHandler.remove();
        ioHandler.update();
        ioHandler.query()
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章