当前位置:  编程技术>移动开发

Android源码学习之工厂方法模式应用及优势介绍

    来源: 互联网  发布时间:2014-10-12

    本文导语:  工厂方法模式定义: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的...

工厂方法模式定义:
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类中有这么一个函数:
代码如下:

/**
* This method is called after {@link #onStart} when the activity is
* being re-initialized from a previously saved state, given here in
* savedInstanceState. Most implementations will simply use {@link #onCreate}
* to restore their state, 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. The default
* implementation of this method performs a restore of any view state that
* had previously been frozen by {@link #onSaveInstanceState}.
*
*

This method is called between {@link #onStart} and
* {@link #onPostCreate}.
*
* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
*
* @see #onCreate
* @see #onPostCreate
* @see #onResume
* @see #onSaveInstanceState
*/
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (mWindow != null) {
Bundle windowState = savedInstanceState.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 {
/**
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected ListAdapter mAdapter;
/**
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected ListView mList;
private Handler mHandler = new Handler();
private boolean mFinishedStart = false;
private Runnable mRequestFocus = new Runnable() {
public void run() {
mList.focusableViewAvailable(mList);
}
};
/**
* This method will be called when an item in the list is selected.
* Subclasses should override. Subclasses can call
* getListView().getItemAtPosition(position) if they need to access the
* data associated with the selected item.
*
* @param l The ListView where the click happened
* @param v The view that was clicked within the ListView
* @param position The position of the view in the list
* @param id The row id of the item that was clicked
*/
protected void onListItemClick(ListView l, View v, int position, long id) {
}
/**
* Ensures the list view has been created before Activity restores all
* of the view states.
*
*@see Activity#onRestoreInstanceState(Bundle)
*/
@Override
protected void onRestoreInstanceState(Bundle state) {
ensureList();
super.onRestoreInstanceState(state);
}
/**
* @see Activity#onDestroy()
*/
@Override
protected void onDestroy() {
mHandler.removeCallbacks(mRequestFocus);
super.onDestroy();
}
/**
* Updates the screen state (current list and other views) when the
* content changes.
*
* @see Activity#onContentChanged()
*/
@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;
}
/**
* Provide the cursor for the list view.
*/
public void setListAdapter(ListAdapter adapter) {
synchronized (this) {
ensureList();
mAdapter = adapter;
mList.setAdapter(adapter);
}
}
/**
* Set the currently selected list item to the specified
* position with the adapter's data
*
* @param position
*/
public void setSelection(int position) {
mList.setSelection(position);
}
/**
* Get the position of the currently selected list item.
*/
public int getSelectedItemPosition() {
return mList.getSelectedItemPosition();
}
/**
* Get the cursor row ID of the currently selected list item.
*/
public long getSelectedItemId() {
return mList.getSelectedItemId();
}
/**
* Get the activity's list view widget.
*/
public ListView getListView() {
ensureList();
return mList;
}
/**
* Get the ListAdapter associated with this activity's ListView.
*/
public ListAdapter getListAdapter() {
return mAdapter;
}
private void ensureList() {
if (mList != null) {
return;
}
setContentView(com.android.internal.R.layout.list_content_simple);
}
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);
代码如下:

/**
* Ensures the list view has been created before Activity restores all
* of the view states.
*
*@see Activity#onRestoreInstanceState(Bundle)
*/
@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()函数:
代码如下:

/**
* Set the activity content from a layout resource. The resource will be
* inflated, adding all top-level views to the activity.
*
* @param layoutResID Resource ID to be inflated.
*
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initActionBar();
}
/**
* Set the activity content to an explicit view. This view is placed
* directly into the activity's view hierarchy. It can itself be a complex
* view hierarchy. When calling this method, the layout parameters of the
* specified view are ignored. Both the width and the height of the view are
* set by default to {@link ViewGroup.LayoutParams#MATCH_PARENT}. To use
* your own layout parameters, invoke
* {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
* instead.
*
* @param view The desired content to display.
*
* @see #setContentView(int)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
public void setContentView(View view) {
getWindow().setContentView(view);
initActionBar();
}
/**
* Set the activity content to an explicit view. This view is placed
* directly into the activity's view hierarchy. It can itself be a complex
* view hierarchy.
*
* @param view The desired content to display.
* @param params Layout parameters for the view.
*
* @see #setContentView(android.view.View)
* @see #setContentView(int)
*/
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开发学习之WallPaper设置壁纸详细介绍与实例
  • Android源码学习之观察者模式应用及优点介绍
  • Android源码学习之单例模式应用及优点介绍
  • Android源码学习之组合模式定义及应用
  • Unbutu中利用Shell自动编译Android源码
  • Android源码构建系统 Buck
  • Android修改源码解决Alertdialog触摸对话框边缘消失的问题
  • Eclipse开发环境导入android sdk的sample中的源码
  • Windows下获取Android 源码方法的详解
  • android开机自启动原理与实现案例(附源码)
  • 比较完整的android MP3 LRC歌词滚动高亮显示(附源码)
  • android apk反编译到java源码的实现方法
  • 基于Android设计模式之--SDK源码之策略模式的详解
  • Android利用ViewPager实现滑动广告板实例源码
  • Android笔记之:CM9源码下载与编译的应用
  • Android 使用Gallery实现3D相册(附效果图+Demo源码)
  • Android中实现地址栏输入网址能浏览该地址网页源码并操作访问网络
  • Android中实现多行、水平滚动的分页的Gridview实例源码
  • Android系统联系人全特效实现(上)分组导航和挤压动画(附源码)
  • Android 2.3 拨号上网流程从源码角度进行分析
  • 从零开始学android实现计算器功能示例分享(计算器源码)
  • android的消息处理机制(图文+源码分析)—Looper/Handler/Message
  • Android源码中的目录结构详解
  • android 九宫格滑动解锁开机实例源码学习
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 申请Android Map 的API Key(v2)的最新申请方式(SHA1密钥)
  • Android瀑布流实例 android_waterfall
  • Android开发需要的几点注意事项总结
  • Android系统自带样式 (android:theme)
  • android 4.0 托管进程介绍及优先级和回收机制
  • Android网络共享软件 Android Wifi Tether
  • Android访问与手机通讯相关类的介绍
  • Android 图标库 Android GraphView
  • Android及andriod无线网络Wifi开发的几点注意事项
  • 轻量级Android开发工具 Android Tools
  • Android 2.3 下StrictMode介绍
  • Android 开发环境 Android Studio
  • IDEA的Android开发插件 idea-android
  • Android手机事件提醒 Android Notifier
  • XBMC的Android客户端 android-xbmcremote
  • Android小游戏 Android Shapes
  • Android电池监控 Android Battery Dog
  • android开发:“android:WindowTitle”没有对应项no resource
  • Android 上类似IOS 的开关控件。 Android ToggleButton
  • Android 将 android view 的位置设为右下角的解决方法
  • Android 2D游戏引擎 Android Angle


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3