目錄
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()
}