Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
常用的工厂方法模式结构:
如上图所示(截取自《Head First Design Patterns》一书),主要包括四个部分:
抽象产品类Product负责定义产品的共性,实现对事物抽象的定义;Creator是抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。其中在《Head First Design Patterns》对工厂方法模式做了细节的说明,原文如下:
As in the official definition, you'll often hear developers say that the Factory Method lets subclasses decide which class to instantiate. They say “decides” not because the pattern allows subclasses themselves to decide at runtime, but because the creator class is written without knowledge of the actual products that will be created, which is decided purely by the choice of the subclass that is used.
工厂方法模式有什么优势呢:
良好的封装性,代码结构清楚。一个对象创建具有条件约束的,如果一个调用者需要一个具体的产品对象,只要知道这个产品的类名就可以了,不用知道创建对象的过程,降低模块间的耦合。
可扩展性好。在增加产品类的情况下,只要适当的修改具体的工厂类或扩展一个工厂类,就可以完成。
屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不用改变。因为产品类的实例化工作是由工厂类负责的,一个产品对象具体由哪一个产品生成是由工厂类决定的。此外工厂方法模式是典型的松耦合结构。高层模块只需要知道产品的抽象类,其他的实现类都不用关系,符合迪米特法则、依赖倒置原则、里氏替换原则等。
在Android源码中,ListActivity继承自Activity,将Activity作为工厂方法,生成具有ListView特点的Activity,对ListActivity的说明如下:
An activity that displays a list of items by binding to a data source such as an array or Cursor, and exposes event handlers when the user selects an item.
ListActivity hosts a ListView object that can be bound to different data sources, typically either an array or a Cursor holding query results. Binding, screen layout, and row layout are discussed in the following sections.
Screen Layout
ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "@android:id/list" (or listif it's in code)
在Activity类中有这么一个函数:
代码如下:
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
Bundle windowState = savedInstanceStat e.getBundle(WINDOW_HIERARCHY_TAG);
if (windowState != null) {
mWindow.restoreHierarchyState(windowState);
}
}
}
在注释中“but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation.”,英语不太好,但大致的意思是Activity子类可以重载这个函数来决定是否使用默认的实现。
在看子类ListActivity:
代码如下:
public class ListActivity extends Activity {
protected ListAdapter mAdapter;
protected ListView mList;
private Handler mHandler = new Handler();
private boolean mFinishedStart = false;
private Runnable mRequestFocus = new Runnable() {
public void run() {
mList.focusableViewAvailable(mList);
}
};
protected void onListItemClick(ListView l, View v, int position, long id) {
}
@Override
protected void onRestoreInstanceState(Bundle state) {
ensureList();
super.onRestoreInstanceState(state);
}
@Override
protected void onDestroy() {
mHandler.removeCallbacks(mRequestFocus);
super.onDestroy();
}
@Override
public void onContentChanged() {
super.onContentChanged();
View emptyView = findViewById(com.android.internal.R.id.empty);
mList = (ListView)findViewById(com.android.internal.R.id.list);
if (mList == null) {
throw new RuntimeException(
"Your content must have a ListView whose id attribute is " +
"'android.R.id.list'");
}
if (emptyView != null) {
mList.setEmptyView(emptyView);
}
mList.setOnItemClickListener(mOnClickListener);
if (mFinishedStart) {
setListAdapter(mAdapter);
}
mHandler.post(mRequestFocus);
mFinishedStart = true;
}
public void setListAdapter(ListAdapter adapter) {
synchronized (this) {
ensureList();
mAdapter = adapter;
mList.setAdapter(adapter);
}
}
public void setSelection(int position) {
mList.setSelection(position);
}
public int getSelectedItemPosition() {
return mList.getSelectedItemPosition();
}
public long getSelectedItemId() {
return mList.getSelectedItemId();
}
public ListView getListView() {
ensureList();
return mList;
}
public ListAdapter getListAdapter() {
return mAdapter;
}
private void ensureList() {
if (mList != null) {
return;
}
setContentView(com.android.internal.R.layout.list_content_sim ple);
}
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
onListItemClick((ListView)parent, v, position, id);
}
};
}
其中复写了函数onRestoreInstanceState(Bundle state),并在View中设置了默认的setContentView(com.android.internal.R.layout.list_content_simple);
代码如下:
@Override
protected void onRestoreInstanceState(Bundle state) {
ensureList();
super.onRestoreInstanceState(state);
}
。。。
private void ensureList() {
if (mList != null) {
return;
}
setContentView(com.android.internal.R.layout.list_content_simple);
}
Activity中的setContentView()函数:
代码如下:
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initActionBar();
}
public void setContentView(View view) {
getWindow().setContentView(view);
initActionBar();
}
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
initActionBar();
}
总结:Activity作为“工厂方法”,具体View中显示什么由默认设置或者由子类来实现;ListActivity作为具体实现,它决定在View中显示的是ListView;这里的View是Activity中的默认显示,即为“Product”,而ListView是“ConcreteProduct”,由ListActivity来决定显示。
除了ListActivity以外,还有ExpandableListActivity也是以Activity为工厂类,创建自己的显示效果。
本人能力和时间有限(缺少“模式使用”内容,以后会添加),写的很粗糙,恭候大家的批评指正,谢谢~~~ 您可能感兴趣的文章:Android编程设计模式之工厂方法模式实例详解Android设计模式系列之工厂方法模式Android编程设计模式之原型模式实例详解Android编程设计模式之Builder模式实例详解Android编程设计模式之单例模式实例详解Android编程设计模式之观察者模式实例详解基于Android设计模式之--SDK源码之策略模式的详解Android设计模式之适配器(Adapter)模式Android 单例模式 Singleton 简单实例设计模式解析Android设计模式系列之组合模式Android编程设计模式之抽象工厂模式详解