Android中常用的设计模式(一)

单例

概念:确保一个类只有一个实例,并且自行实例化并向整个系统提供整个实例

优点:

1,对于那些耗内存的类,只实例化一次,大大提高性能,尤其是移动开发中

2,程序运行中,始终保持只有一个实例在内存中

public class Singleton {  
    private static volatile Singleton instance = null;  

    private Singleton(){  
    }  

    public static Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}  

构造函数私有化,定义静态函数获得实例就不多说了,这里着重说一下volatile:

volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从内存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.(首先我们要先意识到有这样的现象,编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.
而在这个过程,变量的新值对其他线程是不可见的.而volatile的作用就是使它修饰的变量的读写操作都必须在内存中进行!)

再就是这个双重判断null :

这是因为如果线程A进入了该代码,线程B 在等待,这是A线程创建完一个实例出来后,线程B 获得锁进入同步代码,实例已经存在,木有必要再创建一个,所以双重判断有必要。

哎,不说不说的又写了这么多。

Android中 用到的地方很多,比如Android-Universal-Image-Loader中的单例,EventBus中的单例

最后给出一个管理我们activity的类,可以作为一个简单工具类

public class ActivityManager {  

    private static volatile ActivityManager instance;  
    private Stack<Activity> mActivityStack = new Stack<Activity>();  

    private ActivityManager(){  

    }  

    public static ActivityManager getInstance(){  
        if (instance == null) {  
        synchronized (ActivityManager.class) {  
            if (instance == null) {  
                instance = new ActivityManager();  
            }  
        }  
        return instance;  
    }  

    public void addActicity(Activity act){  
        mActivityStack.push(act);  
    }  

    public void removeActivity(Activity act){  
        mActivityStack.remove(act);  
    }  

    public void killMyProcess(){  
        int nCount = mActivityStack.size();  
        for (int i = nCount - 1; i >= 0; i--) {  
            Activity activity = mActivityStack.get(i);  
            activity.finish();  
        }  

        mActivityStack.clear();  
        android.os.Process.killProcess(android.os.Process.myPid());  
    } 
} 

Builder 模式

还是按部就班的先说一下定义,网上的定义,

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

是不是上来先读了两遍,然后发现,没读懂,没关系,大家基本都没读懂,概念就是比较抽象的,让大家很难理解的,如果简单从这个一个概念就搞懂了这个模式的话,那就不用费力的去查资料整理后边的东西了。
这里我们通过一个栗子来引出Build模。假设有一个Person类,他的一些属性可以为null,可以通过这个类来构架一大批人

public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  

    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public double getHeight() {  
        return height;  
    }  

    public void setHeight(double height) {  
        this.height = height;  
    }  

    public double getWeight() {  
        return weight;  
    }  

    public void setWeight(double weight) {  
        this.weight = weight;  
    }  
}  

然后为了方便,你可能会写这么一个构造函数来穿传属性

public Person(String name, int age, double height, double weight) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
    this.weight = weight;  
} 

或者为了更方便还会写一个空的构造函数

public Person() {  
} 

有时候还会比较懒,只传入某些参数,又会来写这些构造函数

public Person(String name) {  
    this.name = name;  
}  

public Person(String name, int age) {  
    this.name = name;  
    this.age = age;  
}  

public Person(String name, int age, double height) {  
    this.name = name;  
    this.age = age;  
    this.height = height;  
} 

于是就可以来创建各种需要的类

Person p1=new Person();  
Person p2=new Person("张三");  
Person p3=new Person("李四",18);  
Person p4=new Person("王五",21,180);  
Person p5=new Person("赵六",17,170,65.4);

其实这种写法的坏处在你写的过程中想摔键盘的时候就该想到了,既然就是一个创建对象的过程,怎么这么繁琐,并且构造函数参数过多,其他人创建对象的时候怎么知道各个参数代表什么意思呢,这个时候我们为了代码的可读性,就可以用一下Builder模式了
给Person类添加一个静态Builder类,然后修改Person的构造函数,如下,

public class Person {  
    private String name;  
    private int age;  
    private double height;  
    private double weight;  

    privatePerson(Builder builder) {  
        this.name=builder.name;  
        this.age=builder.age;  
        this.height=builder.height;  
        this.weight=builder.weight;  
    }  
    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public double getHeight() {  
        return height;  
    }  

    public void setHeight(double height) {  
        this.height = height;  
    }  

    public double getWeight() {  
        return weight;  
    }  

    public void setWeight(double weight) {  
        this.weight = weight;  
    }  

    static class Builder{  
        private String name;  
        private int age;  
        private double height;  
        private double weight;  
        public Builder name(String name){  
            this.name=name;  
            return this;  
        }  
        public Builder age(int age){  
            this.age=age;  
            return this;  
        }  
        public Builder height(double height){  
            this.height=height;  
            return this;  
        }  

        public Builder weight(double weight){  
            this.weight=weight;  
            return this;  
        }  

        public Person build(){  
            return new Person(this);  
        }  
    }  
}  

从上边代码我们可以看到我们在Builder类中定义了一份跟Person类一样的属性,通过一系列的成员函数进行赋值,但是返回的都是this,最后提供了一个build函数来创建person对象,对应的在Person的构造函数中,传入了Builder对象,然后依次对自己的成员变量进行赋值。此外,Builder的成员函数返回的都是this的另一个作用就是让他支持链式调用,使代码可读性大大增强
于是我们就可以这样创建Person对象

Person.Builder builder=new Person.Builder();  
Person person=builder  
        .name("张三")  
        .age(18)  
        .height(178.5)  
        .weight(67.4)  
        .build();  

是不是有那么点感觉了呢
Android中大量地方运用到了Builder模式,比如常见的对话框创建

AlertDialog.Builder builder=new AlertDialog.Builder(this);  
AlertDialog dialog=builder.setTitle("标题")  
        .setIcon(android.R.drawable.ic_dialog_alert)  
        .setView(R.layout.myview)  
        .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  

            }  
        })  
        .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  

            }  
        })  
        .create();  
dialog.show();  

其实在java中StringBuilder 和StringBuffer都用到了Builder模式,只不过是稍微简单一点了
Gson中的GsonBuilder

GsonBuilder builder=new GsonBuilder();  
Gson gson=builder.setPrettyPrinting()  
        .disableHtmlEscaping()  
        .generateNonExecutableJson()  
        .serializeNulls()  
        .create(); 

网络框架OKHttp

Request.Builder builder=new Request.Builder();  
Request request=builder.addHeader("","")  
    .url("")  
    .post(body)  
    .build();  

可见大量框架运用了Builder 设计模式,总结一下吧:

定义一个静态内部类Builder,内部成员变量跟外部一样
Builder通过一系列方法给成员变量赋值,并返回当前对象(this)
Builder类内部提供一个build方法方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有化构造方法,该构造方法的参数就是内部类Builder
外部类提供一个私有化的构造方法供内部类调用,在该构造函数中完成成员变量的赋值

观察者模式

二话不说,上来就是定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新

这个好像还好理解那么一点点,不过还是先来讲个情景,

天气预报的短信服务,一旦付费订阅,每次天气更新都会向你及时发送

其实就是我们无需每时每刻关注我们感兴趣的东西,我们只需要订阅它即可,一旦我们订阅的事务有变化了,被订阅的事务就会即时的通知我们

我们来看一下观察者模式的组成:

  • 观察者,我们称它为Observer,有时候我们也称它为订阅者,即Subscriber
  • 被观察者,我们称它为Observable,即可以被观察的东西,有时候还会称之为主题,即Subject

至于观察者模式的具体实现,java里为我们提供了Observable类和Observer接口供我们快速实现该模式,但是这里为了加深印象,不用这个两个类
我们来模拟上边的场景,先定义一个Weather的类

public class Weather {  
    private String description;  

    public Weather(String description) {  
        this.description = description;  
    }  

    public String getDescription() {  
        return description;  
    }  

    public void setDescription(String description) {  
        this.description = description;  
    }  

    @Override  
    public String toString() {  
        return "Weather{" +  
                "description='" + description + '\'' +  
                '}';  
    }  
}  

然后定义我们的被观察着,我们希望它能够通用,所以定义成泛型,内部应该暴露出register和unRegister供观察者订阅和取消订阅,至于观察者的保存,我们用ArrayList即可,另外,当主题发生变化的时候,需要通知观察者来做出响应,还需要一个notifyObservers方法,具体实现如下:

public class Observable<T> {  
    List<Observer<T>> mObservers = new ArrayList<Observer<T>>();  

    public void register(Observer<T> observer) {  
        if (observer == null) {  
            throw new NullPointerException("observer == null");  
        }  
        synchronized (this) {  
            if (!mObservers.contains(observer))  
                mObservers.add(observer);  
        }  
    }  

    public synchronized void unregister(Observer<T> observer) {  
        mObservers.remove(observer);  
    }  

    public void notifyObservers(T data) {  
        for (Observer<T> observer : mObservers) {  
            observer.onUpdate(this, data);  
        }  
    }  

}  

而我们的观察者只需要实现一个观察者的接口Observer,该接口也是泛型的

public interface Observer<T> {  
    void onUpdate(Observable<T> observable,T data);  
}  

一旦订阅的主题发生了变化,就会调用该接口
用一下,我们定义一个天气变化的主题,也就是被观察者,再定义两个观察者来观察天气的变化,一旦变化了就打印出天气的情况,注意,一定要用register方法来注册,否则观察者收不到变化的信息,而一旦不感兴趣,就可以调用unregister方法

public class Main {  
    public static void main(String [] args){  
        Observable<Weather> observable=new Observable<Weather>();  
        Observer<Weather> observer1=new Observer<Weather>() {  
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("观察者1:"+data.toString());  
            }  
        };  
        Observer<Weather> observer2=new Observer<Weather>() {  
            @Override  
            public void onUpdate(Observable<Weather> observable, Weather data) {  
                System.out.println("观察者2:"+data.toString());  
            }  
        };  

        observable.register(observer1);  
        observable.register(observer2);  


        Weather weather=new Weather("晴转多云");  
        observable.notifyObservers(weather);  

        Weather weather1=new Weather("多云转阴");  
        observable.notifyObservers(weather1);  

        observable.unregister(observer1);  

        Weather weather2=new Weather("台风");  
        observable.notifyObservers(weather2);  

    }  
}  

输出也灭有问题
观察者1:Weather{description=’晴转多云’}
观察者2:Weather{description=’晴转多云’}
观察者1:Weather{description=’多云转阴’}
观察者2:Weather{description=’多云转阴’}
观察者2:Weather{description=’台风’}

好,我们来看一下在Android中的应用,从最简单的开始,Button的点击事件

Button btn=new Button(this);  
btn.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.e("TAG","click");  
    }  
});  

严格意义来说,这只能算是一个回调,但是我们可以把它看做是一个一对一的观察者模式,其实,只要是set系列的设置监听事件的方法最多都只能算是一种回调,但是一些监听器是通过add添加的,这些就观察者模式了比如,RecyclerView的addScrollListener方法

private List<OnScrollListener> mScrollListeners;  
public void addOnScrollListener(OnScrollListener listener) {  
    if (mScrollListeners == null) {  
        mScrollListeners = new ArrayList<OnScrollListener>();  
    }  
    mScrollListeners.add(listener);  
}  
public void removeOnScrollListener(OnScrollListener listener) {  
    if (mScrollListeners != null) {  
        mScrollListeners.remove(listener);  
    }  
}  
public void clearOnScrollListeners() {  
    if (mScrollListeners != null) {  
        mScrollListeners.clear();  
    }  
}  

然后有滚动事件时就触发观察者方法进行回调

public abstract static class OnScrollListener {  
    public void onScrollStateChanged(RecyclerView recyclerView, int newState){}  
    public void onScrolled(RecyclerView recyclerView, int dx, int dy){}  
}  

void dispatchOnScrolled(int hresult, int vresult) {  
    //...  
    if (mScrollListeners != null) {  
        for (int i = mScrollListeners.size() - 1; i >= 0; i--) {  
            mScrollListeners.get(i).onScrolled(this, hresult, vresult);  
        }  
    }  
}  
void dispatchOnScrollStateChanged(int state) {  
    //...  
    if (mScrollListeners != null) {  
        for (int i = mScrollListeners.size() - 1; i >= 0; i--) {  
            mScrollListeners.get(i).onScrollStateChanged(this, state);  
        }  
    }  
}  

另外广播机制,本质也是观察者模式
调用registerReceiver方法注册广播,调用unregisterReceiver方法取消注册,之后使用sendBroadcast发送广播,之后注册的广播会受到对应的广播信息,这就是典型的观察者模式

开源框架EventBus也是基于观察者模式的,

观察者模式的注册,取消,发送事件三个典型方法都有

EventBus.getDefault().register(Object subscriber);  
EventBus.getDefault().unregister(Object subscriber);  

EventBus.getDefault().post(Object event);  

比较重量级的库RxJava,创建一个被观察者

Observable<String> myObservable = Observable.create(    
    new Observable.OnSubscribe<String>() {    
        @Override    
        public void call(Subscriber<? super String> sub) {    
            sub.onNext("Hello, world!");    
            sub.onCompleted();    
        }    
    }    
);  

创建一个观察者,也就是订阅者

Subscriber<String> mySubscriber = new Subscriber<String>() {    
    @Override    
    public void onNext(String s) { System.out.println(s); }    

    @Override    
    public void onCompleted() { }    

    @Override    
    public void onError(Throwable e) { }    
};  

观察者进行事件的订阅

myObservable.subscribe(mySubscriber);  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值