Android 经常使用设计模式(一)
由于项目变更的频繁性,作为一名程序猿,我们须要掌握设计模式的必要性。就不言而喻~~。以下就是一些我自己学习的设计模式总结。
接下来,主要是针对几个比較经常使用模式进行解说,主要是以下几种:
- 观察者模式
- 适配器模式
- 代理模式
- 工厂模式
- 单例模式
- 命令模式
1.观察者模式(Observer Pattern)
释义:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同一时候监听某一个主题对象,这个主题对象在状态上发生变化时,会通知全部观察者对象,使他们能够自己主动更新自己。
故事理解:观察者想知道公司全部MM的情况,仅仅要增加公司的MM情报邮件组即可了,tom负责搜集情报,当发现新情报时,不用一个一个通知我们,直接公布给邮件组。我们作为订阅者(观察者)就能够及时收到情报啦。
常见实例:1.BaseAdapter.registerDataSetObserver和BaseAdapter.unregisterDataSetObserver双方法来向BaseAdater注冊、注销一个DataSetObserver ; 2.使用ContentObserver去监听数据库变化。
适用场景:1.当对一个对象的改变须要同一时候改变其它对象,而不知道详细有多少对象有待改变。2.当一个对象必须通知其它对象。而它又不能假定其它对象是谁.
观察者模式主要有观察者和被观察者2个对象。在该模式中。Observable表示被观察者,这个对象是一个抽象类。仅仅能被继承。 Observer表示观察者,他是一个接口。所以观察者能够有多个。实现了该接口的类都是属于观察者。
这是网上一个生动仔细的demo:
被观察者:
public class MyPerson extends Observable {
private int age;
private String name;
private String sax;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
setChanged();
notifyObservers();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
setChanged();
notifyObservers();
}
public String getSax() {
return sax;
}
public void setSax(String sax) {
this.sax = sax;
}
@Override
public String toString() {
return "MyPerson [age=" + age + ", name=" + name + ", sax=" + sax + "]";
}
}
MyPerson是被观察者,类中调用了setChange()以及notifyObservers()两个方法。前者是告知数据改变,后者是发送信号通知观察者。
观察者:
public class MyObserver implements Observer {
private int i;
private MyPerson myPerson;//观察的对象
public MyObserver(int i){
System.out.println("我是观察者---->" + i);
this.i = i;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public MyPerson getMyPerson() {
return myPerson;
}
public void setMyPerson(MyPerson myPerson) {
this.myPerson = myPerson;
}
@Override
public void update(Observable observable, Object data) {
System.out.println("观察者---->"+ i +"得到更新!");
this.myPerson = (MyPerson)observable;
System.out.println(((MyPerson)observable).toString());
}
}
观察者须要实现Observer接口,当中仅仅有一个update方法。当观察者收到 (被观察者)的通知信号。就会执行该动作。
2.适配器模式(Adapter Pattern)
释义:把一个类的接口变换成client所期待的还有一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。
适配类能够依据參数返还一个合适的实例给client。
故事理解:在朋友聚会上碰到了一个美女Sarah。从香港来的,可我不会说粤语。她不会说普通话,仅仅好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah能够相互交谈了(也不知道他会不会耍我)。
常见实例:ListView用于显示列表数据,可是作为列表数据集合有非常多形式。有Array,有Cursor,我们须要相应的适配器作为桥梁,处理相应的数据(并能形成ListView所须要的视图)。
适用场景:1.业务的接口与工作的类不兼容,(比方:类中缺少实现接口的某些方法)但又须要两者一起工作。2. 在现有接口和类的基础上为新的业务需求提供接口。
适配器模式分为类适配器模式和对象适配器模式。
关于类适配模式。由于java的单继承,所以在已继承一个类时。另外的仅仅能是接口,须要手动实现相应的方法,这样在client就能够创建任一种符合需求的子类。来实现详细功能。而第二种对象适配器,它不是使用继承再实现的方式,而是使用直接关联,或者称为托付的方式,详细可见该博客详细介绍适配器模式(Adapter):类适配器、对象适配器
接下来就以ListView与ArrayAdapter来解说下
ListAdapter:
public interface ListAdapter {
public int getCount();
Object getItem(int position);
long getItemId(int position);
View getView(int position, View convertView, ViewGroup parent);
boolean isEmpty();
}
ListView作为一个client,所须要的目标接口就是ListAdapter,包括getCount(),getItem(),getView()等几个方法。为了兼容List< T >数据类型的数据源。专门定义了ArrayAdapter适配器,说白了。就是针对目标接口对数据源进行兼容修饰。
抽象类BaseAdapter,省略了其它代码,这里仅仅列出两个方法:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
// ... ...
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
public boolean isEmpty() {
return getCount() == 0;
}
}
ArrayAdapter对List< T >进行封装成ListAdapter的实现,满足ListView的调用:
public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
private List<T> mObjects;
//我仅仅列出这一个构造函数。大家懂这个意思即可
public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {
init(context, textViewResourceId, 0, Arrays.asList(objects));
}
private void init(Context context, int resource, int textViewResourceId, List<T> objects) {
mContext = context;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mResource = mDropDownResource = resource;
mObjects = objects; //引用对象,也是表达了组合优于继承的意思
mFieldId = textViewResourceId;
}
public int getCount() {
return mObjects.size();
}
public T getItem(int position) {
return mObjects.get(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
// ... ...
}
我们就如此成功的把List< T > 作为数据源以ListView想要的目标接口的样子传给了ListView。这事实上也是对象适配器的一种。
3.代理模式(Proxy Pattern)
释义: 通过引入一个新的对象来实现对真实对象的操作或将新的对象作为真实对象的一个替身,这种实现机制是代理模式(为其它对象提供一种代理以控制对这个对象的訪问).
故事理解:校园代理是为他相应的上司作代理,而这个校园代理的工作就是訪问校园中的学生。比如对学生进行问卷之类的事。
学生就是官方说法中的其它对象,校园代理的上司就通过控制这个校园代理来控制对学生的訪问。
常见实例:ActivityManagerProxy类就是一个代理。它是ActivityManagerNative的代理,也就是说ActivityManagerProxy是所说的Proxy类。而ActivityManagerNative就相当于“上司角色“类,它们都有一个共同拥有的接口IActivityManager。ActivityManager。它相当于代理模式的client。在这个类中,能够看到大量的getxxx函数,这些函数,都会调用到ActivityManagerNative类的getDefault()方法,而该方法会获得一个共用的单例的IActivityManager引用。然后通过多态来调用代理中的实现
适用场景:代理模式的应用场合分几种:远程代理,虚拟代理,安全代理等,详细可见为别人做嫁衣—-代理模式
请看以下一张结构图(网上看到的一个仔细生动的样例):
Subject类:定义了RealSubject和Proxy的共用接口,这样就能够在不论什么 使用RealSubject的地方都能够用Proxy。
RealSubject类:定义Proxy所代表的真实实体。
Proxy类:保存一个引用使得代理能够訪问实体,并提供一个与Subject的接口同样的接口。这样代理就能够用来替代实体。
接下来,我们来实现该模式:
1.Subject类 :Image.java
/**
* Subject类
*/
public abstract class Image {
public abstract void displayImage();
}
2.RealSubject类:RealImage.java
import com.andyidea.patterns.subject.Image;
/**
* RealSubject类
*/
public class RealImage extends Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
@Override
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
3.proxy类:ProxyImage.java
import com.andyidea.patterns.realsubject.RealImage;
import com.andyidea.patterns.subject.Image;
/**
* Proxy类
*/
public class ProxyImage extends Image {
private String filename;
private Image image;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void displayImage() {
if(image == null){
image = new RealImage(filename);
}
image.displayImage();
}
}
4.client測试类:ProxyClient.java
import com.andyidea.patterns.proxy.ProxyImage;
import com.andyidea.patterns.subject.Image;
/**
* 代理模式client測试类
*/
public class ProxyClient {
public static void main(String[] args) {
System.out.println("Welcome to my Blog!" +"\n"
+"Proxy Patterns." +"\n"
+"-------------------------------");
Image mImage1 = new ProxyImage("My.Image1");
Image mImage2 = new ProxyImage("My.Image2");
mImage1.displayImage();
mImage2.displayImage();
}
}
执行结果例如以下:
Welcome to my Blog!
Proxy Patterns
-------------------------------
Loading My.Image1
Displaying My.Image1
Loading My.Image2
Displaying My.Image2
总结来说,代理类就是对实体保存一个引用。同一时候也实现了实体一样的接口方法,这样。就能够替代实体了!!
以上就是观察者模式。适配器模式,代理模式的认识,接下来会在 Android 经常使用设计模式(二)里,继续对余下的三种模式进行阐述。
Android 经常使用设计模式(一)的更多相关文章
- 《Android源码设计模式》学习笔记之ImageLoader
微信公众号:CodingAndroid cnblog:http://www.cnblogs.com/angel88/ CSDN:http://blog.csdn.net/xinpengfei521 需 ...
- [转] Android中的设计模式-备忘录模式
转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫 ...
- Android中的设计模式之观察者模式
参考 <设计模式:可复用面向对象软件的基础 >5.7 Observer 观察者 对象行为型模式 <设计模式解析> 18.4 Observer模式 <Android源码设计 ...
- Android经常使用设计模式(二)
继上一篇 Android经常使用设计模式(一)里认识了观察者.适配器.代理等三种模式,这一篇将会解说下面三种模式: 工厂模式 单例模式 命令模式 1.工厂模式(Factory Pattern) 工厂模 ...
- [Android]GOF23种设计模式 & Android中的设计模式
GOF23种设计模式 设计原则: 1. 单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因 2. 开放-封闭原则(OCP):软件实体(类.模块.函数等)应该可以扩展,但是不可修改.即对 ...
- Android使用的设计模式2——策略模式
今天讲解一下策略模式,策略模式也是很常用的设计模式,对多种算法或者数据结构选择使用的情况下,经常会使用策略模式来管理这些算法.下面会简单讲解一下策略模式的概念和基本实现.然后结合Android里面的实 ...
- Android使用的设计模式1——观察者模式
设计模式,对程序员来说是一个坎,想在程序员这条路走得更远,设计模式是你的必修课.从大学时代接触GoF到工作几年后重新看设计模式,每次感觉都不一样.这次想借着分析Android Framework源码的 ...
- Android与MVC设计模式
写在前面,之前做过一段时间移动开发,后来因为工作原因搁浅了,最新重新拿起Android权威编程指南学习,顺道做个学习笔记. 首先呢,我想说无论是计算机科班出身还是培训班出身,都听说过高内聚低耦合以及M ...
- android深入之设计模式(一)托付模式
(一)托付模式简单介绍 托付模式是主要的设计模式之中的一个.托付.即是让还有一个对象帮你做事情. 更多的模式,如状态模式.策略模式.訪问者模式本质上是在更特殊的场合採用了托付模式. 托付模式使得我们能 ...
随机推荐
- luogu1771 方程的解
题目大意 对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod 1000(即x^x除以1000的余数),x,k是给定的数.我们要求的是这个不定 ...
- P1025小飞侠的游园方案
描述 经过抽签选择,小智将军第一个进入考场. 菜虫:(身上散射出华贵(?)的光芒)欢迎你,第一位挑战者!! 小智:……(走到菜虫身后,关灯)女王陛下,虽然我们国家现在很富裕,但也请您不要浪费电来用这么 ...
- sublime中BracketHighlighter 插件使用 (转)
sublime中BracketHighlighter 插件使用 1.打开package Control,选择install Package 2.输入BracketHighlighter,回车 3.这样 ...
- Spring中JdbcTemplate中使用RowMapper
转自:https://blog.csdn.net/u012661010/article/details/70049633 1 sping中的RowMapper可以将数据中的每一行数据封装成用户定义的类 ...
- Html+CSS基础之Html
注:本文摘自慕课网http://www.imooc.com HTML+CSS基础课程 本人有道笔记:http://note.youdao.com/noteshare?id=18fa811e9f9e ...
- Python的filter与map内置函数
简单的记录下这两个函数的功能: list(filter(lambda x : x % 2, range(10))) 上例是返回了0-10之间的所有基数组成的列表.filter()有2个参数,第一个参数 ...
- Codeforces Round #447
QAQ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> ...
- 爱,死亡和机器人 第十四集 齐马蓝 中文字幕(Python处理utf8文件获取想要的内容)
处理代码 file = "a.srt" fi = open(file, mode='r') a = fi.readline() i = 1 while len(str(a)) != ...
- 检查点和SCN
有一家叫甲骨文的粮店,老板很严谨,为了防止仓库的粮食在买入卖出的时候发生问题,他制订一套流程,首先进出仓库的每一旦粮食都要求有一个编号(SCN),而且出入库之前必须先放到一个平台上(buffer ca ...
- Verilog之openMSP430(1)
openMSP430_IO interrupt Verilog file: omsp_gpio.v //================================================ ...