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深入之设计模式(一)托付模式
(一)托付模式简单介绍 托付模式是主要的设计模式之中的一个.托付.即是让还有一个对象帮你做事情. 更多的模式,如状态模式.策略模式.訪问者模式本质上是在更特殊的场合採用了托付模式. 托付模式使得我们能 ...
随机推荐
- 0x57 倍增优化DP
真的是下定了巨大的决心来搞这一讲,果不其然耗了一晚上 开车旅行(真的是NOIP的题吗怎么这么恐怖) 首先,先用set把小A和小B从城市i出发,到达的下一个城市预处理出来. f[i][j][k]表示走了 ...
- Date and time types
https://docs.microsoft.com/en-us/sql/t-sql/data-types/date-and-time-types date (Transact-SQL)datetim ...
- 样条函数(spline function)—— 分段多项式函数(piecewise polynomial function)
1. 分段多项式函数 样条函数是某种意义上的分段函数. Spline (mathematics) - Wikipedia 最简单的样条函数是一种分段多项式函数(piecewise polynomial ...
- php 获取随机字符串(原创)
//获取随机数字字母字符串 function get_rand_str($len=8){ $randArr=array_merge(range(0,9),range('a','z'),range('A ...
- python 数据的基本类型(字符串)
python 基础 ascii:字母,数字,特殊字符:1个字节(byte) 8个字位(bit)unicode: 16位两个字节,升级32个字节 4个字位utf-8:最少一个字节 8个表示. 英文 8字 ...
- C Linux read write function extension
前言 - 赠送 readn / writen Linux 上默认的 read 和 write 函数会被信号软中断. 且 read 和 write 函数中第三个参数 count #include < ...
- css3 animate写的超炫3D转换
上一篇中介绍了animate的基本的属性,这一篇讲的则是关于animate以及transforms的使用 <!DOCTYPE html><html lang="en&quo ...
- poj 1161 Floyd+枚举
题意是: 给出n个点,围成m个区域.从区域到另一个区域间需穿过至少一条边(若两区域相邻)——边连接着两点. 给出这么一幅图,并给出一些点,问从这些点到同一个区域的穿过边数最小值. 解题思路如下: 将区 ...
- Svn install and use
1.安装服务 使用yum安装subversion,简单.不繁琐. 1 yum install -y subversion 2.创建版本库 1 2 mkidr /svn/obj ...
- IOS-UITextField-改变光标颜色
方法1: [[UITextField appearance] setTintColor:[UIColor blackColor]]; 这种方法将影响所有TextField. 方法2: textFiel ...