本文地址:http://blog.csdn.net/mba16c35/article/details/43339401
1.Strategy设计模式
(1)定义:把一系列的算法封装成对象,并使他们可相互替换。这样可以使得算法和使用他们的客户解耦。
(2)例子:
public class MyActivty extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView myTextView = (TextView)findViewById(R.id.text_view);
// Define the base URI.
String baseUri = "content://com.paad.earthquake/earthquakes/";
// Contruct an Intent to test if there is an Activity capable of
// viewing the content you are Linkifying. Use the Package Manager
// to perform the test.
PackageManager pm = getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(baseUri));
boolean activityExists = testIntent.resolveActivity(pm) != null;
// Uncomment to apply the match and transform filters
if (activityExists) {
int flags = Pattern.CASE_INSENSITIVE;
Pattern p = Pattern.compile("\\bquake[\\s]?[0-9]+\\b", flags);
Linkify.addLinks(myTextView, p, baseUri,
new MyMatchFilter(), new MyTransformFilter());
}
}
class MyMatchFilter implements MatchFilter {
public boolean acceptMatch(CharSequence s, int start, int end) {
return (start == 0 || s.charAt(start-1) != '!');
}
}
class MyTransformFilter implements TransformFilter {
public String transformUrl(Matcher match, String url) {
return url.toLowerCase().replace(" ", "");
}
}
}
这里的MyMatchFilter和MyTransformFilter就是策略,它们封装了匹配算法并传给Linkify对象。这样只要实现MatchFilter和TransformFilter就可以自定义自己特定算法,而且可以在运行时改变自己自己的算法,因为用的是对象组合的结构。客户则需要针对接口编程,而不受新算法的影响,这里符合了开闭原则(客户对修改封闭,不需要修改客户代码,同时对新算法开放)
2.Adapter模式和观察者模式
(1)定义:
Apdater模式:将一个类的接口转换成客户希望的另外一个接口。Adapter使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Observer模式:定义对象间的一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。
(2)这两个模式在Apater里得到充分运用。
Adapter相当于数据和ListView之间的桥梁,可以适配各种数据类型和扩展了AdapterView的视图组(如ListView或Gallery),堪称Adapter模式的经典例子。Android中的Adapter实际上可以将任意类型的数据和ApaterView之间适配。
另外,当调用Adapter的notifyDataSetChange的时候,实际是运用了观察者模式.
例子:
这是Apdater接口里的两个函数。
/**
* Register an observer that is called when changes happen to the data used by this adapter.
*
* @param observer the object that gets notified when the data set changes.
*/
void registerDataSetObserver(DataSetObserver observer);
/**
* Unregister an observer that has previously been registered with this
* adapter via {@link #registerDataSetObserver}.
*
* @param observer the object to unregister.
*/
void unregisterDataSetObserver(DataSetObserver observer);</span>
我们看看BaseApdater的实现(和主题无关的我就不复制了)
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
代码中的mDataSetObservable意思是可被观察者,指的是BaseApdater自己,这里用了组合而不是继承。当我们调用notifyDataSetChanged的时候,就会调用mDataSetObservalbe的notifyChanged,其中会逐一调用观察者的onChanged函数,那么观察者就知道BaseAdapter的数据有变化并可以做出响应了。
以下是DataSetObservable的notifyChanged函数:
/**
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
*/
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
还有一个观察者模式的例子是AppWidgetManager中包含的notifyAppWidgetViewDataChanged方法,该方法允许指定一个要更新的WidgetID(或ID数组),以及该Widget中低层数据源已经发生变化的集合View的资源ID:
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_stack_view);
这将导致相关的RemoteViewsFactory的onDataSetChanged处理程序执行,然后进行元数据调用,最后再重新创建每个View。
我们可以看到,观察者模式非常适合在GUI中解耦界面元素和Model。设想如果不是使用观察者模式,界面元素可能要采用轮询的方式去检查Model有没有变化,这样效率就相当低下了。
又设想如果Model直接针对具体的界面元素类发消息,通知界面Model发生了变化,那么这部分的代码就没法应用到别的界面类,而界面类也很难在运行时动态替换相关联的Model。所以在界面元素类和Model顶部我们又抽象出观察者和被观察者两个抽象接口,而且用组合的方式建立两者的关系,这就将二者完全解耦了--界面可以在运行时替换自己的Model,Model也可以在运行时删除或增加和自己对应的界面类。
如果我们将View和Modle之间的交互过程进一步封装到一个中介者,即把两者的通信都集中在Controller中,就变成了接下来要讲的MVC模式。Controller进一步分割了View和Modle的职责,体现了单一职责原则。
3.MVC (Model-View-Controller)
(1)M是指逻辑模型,V是指视图模型,C则是控制器。一个逻辑模型可以对于多种视图模型,比如一批统计数据你可以分别用柱状图、饼图来表示。一种视图模型也可以对于多种逻辑模型。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
MVC 基本处理流程 如下:
用户与视图交互,视图接爱并反馈用户的动作;视图把用户的请求传给相应的控制器,由控制器决定调用哪个模型,然后由模型调用相应的业务逻辑对用户请求进行加工处理,如果需要返回数据,模型会把相应的数据返回给控制器,由控制器调用相应的视图,最终由视图格式化和渲染返回的数据,对于返回的数据完全可以增加用户体验效果展现给用户。
Android中界面部分也采用了当前比较流行的MVC框架,在Android中:
1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如何你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。
2) 控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3) 模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。
总结来说,xml布局文件是view相当于JSP页面; activity和intent起到了controller的作用; provider对数据层做了良好的封装,而且provider把数据管理的范畴从数据库泛化到了数据的概念,不光管理数据记录,只要是数据文件(图片、视频、声音文件、所有其他的一切的file)都纳入管理,且提供了数据共享的机制,这是比较出彩的地方; broadcastreceiver提供了一种良好的消息机制,使得一个应用不再是一个信息孤岛,而是和其他的应用、服务等构成了信息网络,从而极大的丰富了应用的开发空间,给了应用开发者极大的想象创造的可能。
(2)那么究竟该如何划分这几层结构呢?我觉得可以换个思路出发,我们究竟该如何合理地组织一个Android应用程序呢?我们不必教条地、具有成见地将原先系统划分结构带入到这样一个新的框架结构中,而是需要在这个特定结构中发挥其框架的效果:
1)xml布局负责将界面布局做好,并且尽量做到合理分割与减少层次
2)Activity做好控件事件绑定与业务流程控制
3)Intent做好Activity间的session传递管理
4)自己创建Model(可以通过Observer模式进行绑定处理、并且包装好各种provider)将处理数据的工作做好。不建议简单地将各个数据字段散乱地存放在Activity周围,而是借助数据Bean的思路存放在Model下面,这样在Model数据项变得庞大后难于管理与重构,而且这多为非面对对象的设计方案。
5)Adapter是数据与呈现的粘合剂。Adapter是Model和View中的桥梁,就是 Controller。
4.代理模式
5.Template Method
public abstract class SQLiteOpenHelper {
public synchronized SQLiteDatabase getWritableDatabase() {
……
boolean success = false;
SQLiteDatabase db = null;
if (mDatabase != null) mDatabase.lock();
try {
mIsInitializing = true;
if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
db = mContext.openOrCreateDatabase(mName, 0, mFactory, mErrorHandler);
}
int version = db.getVersion();
if (version != mNewVersion) {
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if ( mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
……
}
public abstract void onCreate(SQLiteDatabase db);
public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
throw new SQLiteException("Can't downgrade database from version " +
oldVersion + " to " + newVersion);
}
public void onOpen(SQLiteDatabase db) {}
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
其中ServiceHandle是在IntentService的onCreate方法创建的,负责在工作线程中处理我们的intent。注意到,ServiceHandle的handleMessage是一个模版方法,该方法调用了开发者将会override的onHandleIntent,并在处理完之后终止自己。因为ServiceHandle是IntentService的一个内部类,持有外部类IntentService对象的引用,因此可以调用IntentService的抽象方法onHandleIntent。可以看到TemplateMethod非常适合用于构建框架。
6.Builder(生成器)
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle("Test")
.setIcon(R.drawable.ic_launcher)
.setMessage("Test");
builder.create().show();
AlertDialog.Builder是典型的Builder模式。AlertDialog具有复杂的构造参数,如果直接在AlertDialog的构造函数传入这些参数,AlertDialog的构造函数会变得过于复杂而难以使用,而且不是所有代码都需要全部的构造参数,这样又会导致很多的重载构造函数。如果把这些参数都包装成一个对象(在Builder中也是这样)给开发者使用,又暴露了AlertDialog的内部实现。
Notification.Builder builder =
new Notification.Builder(MyActivity.this);
builder.setSmallIcon(R.drawable.ic_launcher)
.setTicker("Notification")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND |
Notification.DEFAULT_VIBRATE)
.setSound(
RingtoneManager.getDefaultUri(
RingtoneManager.TYPE_NOTIFICATION))
.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 })
.setLights(Color.RED, 0, 1);
Notification notification = builder.getNotification();