从Android项目学习设计模式

这个月看了一遍《Android源码设计模式解析与实战》,又一次被android中framework层的设计震惊了,也得到了一些学习的心得体会,“想要理解一个概念,要先理解why,然后才深入how,不能深入细节而忘了初衷”。

面向对象六大原则

设计模式其实就是面向对象的六大原则的体现。

S:单一职责(Single Responsibility Principle)一个类的职责应该只有一个。

O:开闭原则(Open Close Principle)一个对象应该对修改是封闭的,对扩展是开放的。(使用接口实现)

L:里氏替换(Liskov Substitution Principle)(子类能替换父类)

I:接口隔离(Interface Segregation Principle)(类依赖应该建立在最小接口上)

D:依赖倒置(Dependence Inversion Principle)(参考UML图,使用类指向被依赖的类,倒置后使用类指向接口,实现类也指向接口)

迪米特原则(Law of Demeter)一个对象应该与其他对象有最少的了解(参考中介模式,)

一、创建型模式

1、Singleton(单例)

实际应用:ImageLoader(双重校验锁DCL),ActivityThread,ActivityManagerNative(懒汉式),WindowManagerGlobal(懒汉式)

懒汉式:

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
           if (mInstance == null) {
               mInstance = create();
           }
           return mInstance;
        }
    }
}

DCL

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

静态内部类

class Singleton {
    private Singleton() {}
    private static class SingletonHolder {
        private static Singleton mInstance = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.mInstance;
    }
}

2、Factory Method(工厂方法)

实际应用:BitmapFactory(简单工厂或静态工厂),Iterable

有的书上说简单工厂并不算工厂模式,真正意义上的工厂方法模式里,“工厂方法”其实是一个抽象方法,该模式拥有不同的工厂类,不同的工厂类实现了各自的工厂方法,例如ArrayListIterator,LinkIterator都可以算是一个工厂,next方法,previous方法都可以看做是一个工厂方法。

public class FactoryMethon {
    public static void main(String[] args) {
        // 简单工厂
        Product p = SimpleFactory.create("A");
        p.method();
        // 工厂方法
        Factory f = new ConreteFactoryA();
        p = f.create();
        p.method();
        f = new ConreteFactoryB();
        p = f.create();
        p.method();
    }
}

abstract class Product {
    abstract void method();
}

class ConcreteProductA extends Product {

    @Override
    void method() {
        System.out.println("ConcreteProductA");
    }
}

class ConcreteProductB extends Product {

    @Override
    void method() {
        System.out.println("ConcreteProductB");
    }
}

// 简单工厂
class SimpleFactory {
    public static Product create(String s) {
        if ("A".equals(s))
            return new ConcreteProductA();
        if ("B".equals(s))
            return new ConcreteProductB();
        else
            return null;
    }

}

// 工厂方法
abstract class Factory {
    abstract Product create();
}

class ConreteFactoryA extends Factory {
    Product create() {
        return new ConcreteProductA();
    }
}

class ConreteFactoryB extends Factory {
    Product create() {
        return new ConcreteProductB();
    }
}

//ouput:
ConcreteProductA
ConcreteProductA
ConcreteProductB

3、Abstract Factory(抽象工厂)

实际应用:MediaPlayerFactory

抽象工厂相比于工厂方法,多了产品簇的概念,工厂方法是为了当出现新的工厂时可以用很小的代价进行扩展(比如生产智能手机实现了一个createPhone的抽象工厂方法,一开始只有ios和android的工厂实现该方法,当出现新的winphone系统时,只要新建一个winphone工厂来实现createPhone方法就行,代价很小),第一层抽象是根据手机系统的不同,但是如果产品之间也有关联,比如三种系统生产的手机都各自分为高端机型,中端机型,低端机型,这时出现了第二个层次的抽象,高、中、低分别可以抽象出一个接口,再实现三个抽象工厂方法分别生产高、中、低端的手机。

抽象工厂有利于交换产品系列(从一个系统的高端机换到另一系统的高端机),有利于产品一致性(当一个系列的产品被设计成一起工作时)。

抽象工厂不利于接入新的工厂,因为如果新工厂只打算生产低端机,也必须实现生产中端、高端机的接口。

(和工厂方法的明显区别,抽象工厂生产的产品比工厂方法生产的产品多了一层抽象,工厂方法:手机<-android手机,抽象工厂:手机<-高端机<-android手机)

4、Builder(创建者)

实际应用:ImageLoader(ImageLoaderConfiguration.Builder) AlertDialog(AlertDialog.Builder)

builder中链式调用进行配置,最后通过build方法或create方法生成对象并返回。其实就是通过builder对象的相关方法对各个配置项进行配置。

public class BulderPattern {

    public static void main(String[] args) {
        new Dialog.Builder().setTitle("Title").setMessage("Message").build().show();
    }
}

class Dialog {
    String title = "defaultTitle";
    String message = "defaultMessage";

    public void show() {
        System.out.println(title + " " + message);
    }

    public static class Builder {
        private Dialog mD;

        Builder() {
            mD = new Dialog();
        }

        Builder setTitle(String title) {
            mD.title = title;
            return this;
        }

        Builder setMessage(String message) {
            mD.message = message;
            return this;
        }

        Dialog build() {
            return mD;
        }
    }
}

5、Prototype(原型)

实际应用:clone方法 Intent的clone方法是通过new自身来实现的

@Override
public Object clone() {
    return new Intent(this);
}

二、结构型模式

6、Adapter(适配器)

实际应用:ListView中的Adapter

public class AdapterPettern {

    public static void main(String[] args) {
        Target t = new Adapter();
        t.method();
    }
}

interface Target {
    void method();
}

class Adaptee {
    public void methodA() {
        System.out.println("Adaptee Menthod");
    };
}

class Adapter implements Target {
    Adaptee a = new Adaptee();

    @Override
    public void method() {
        a.methodA();
    }
}

7、Bridge(桥接)

实际应用:经常用在一些imp类中,比如WindowManagerImp(感觉其实没必要设计WindowManager接口)

*这个设计模式对于理解android framework的很多设计相当有帮助,可以扩展到其他一些框架的接口类和相关的Imp类进行分析。 用于多维度变化类或者多个树状类之间的耦合的解耦。一个类存在两个独立变化的维度,并且两个维度都需要扩展。

(想到了一个问题,只被一个类继承的接口到底有没有必要把接口抽象出来,比如WindowManagerImpl和WindowManager,有没有必要把WindowManager接口提取出来)

这个模式诠释了(多用组合,少用继承)的好处

public class Bridge {

    public static void main(String[] args) {
        //两个维度,Size和Additive
        LargeCoffee lc = new LargeCoffee(new Additives() {
        });
        lc.makeCoffee();
		
        Suger suger = new Suger();
        lc = new LargeCoffee(suger);
        lc.makeCoffee();
    }
}

abstract class Coffee {
    Additives add;

    Coffee(Additives add) {
        this.add = add;
    }

    abstract void makeCoffee();
}

abstract class Additives {
    String addSomething() {
        return "Nothing";
    };
}

class Suger extends Additives {

    @Override
    String addSomething() {
        return "Suger";
    }
}

class LargeCoffee extends Coffee {
    LargeCoffee(Additives add) {
        super(add);
    }

    @Override
    void makeCoffee() {
        System.out.println("Large " + add.addSomething());
    }
}

8、Composite(组成)

实际应用:View和ViewGroup

ViewGrop继承于View,并且已聚合的方式包含View

class View {
    public void create() {
    };
}

abstract class ViewGroup extends View {
    private ArrayList<View> views = new ArrayList<View>();

    public void addView(View v) {
        views.add(v);
    };

    public void removeView(View v) {
        views.remove(v);
    };
}

9、Decorator(装饰)

实际应用:Context和ContextWrapper,java中的各种输入输出流

包装器Wrapper中包含实际对象的引用,并调用实际对象引用的方法,并对实际对象进行功能扩展。

public class Decorator {

    public static void main(String[] args) {
        ContextImpl ctImp = new ContextImpl();
        new ContextThemeWrapper(ctImp).doSomething();
    }
}

abstract class Context {
    abstract void doSomething();
}

class ContextImpl extends Context {
    void doSomething() {
        System.out.println("ContextImpl doSomething");
    };
}

class ContextWrapper extends Context {
    Context mBase;

    ContextWrapper(Context context) {
        mBase = context;
    }

    void doSomething() {
        mBase.doSomething();
    }
}

class ContextThemeWrapper extends ContextWrapper {

    ContextThemeWrapper(Context context) {
        super(context);
    }

    void doSomething() {
        super.doSomething();
        System.out.println("ContextThemeWrapper doSomething");
    }
}
//output:
ContextImpl doSomething
ContextThemeWrapper doSomething

10、Facade(外观)

实际应用:ContextImpl(管理ActivityManagerNative,PackageManager,ResourcesManager等子系统)

提供了一个高层次接口,方便各个子系统的使用

class ContextImpl {
    AMS ams;
    PKMS pkms;

    void startActivities() {
        ams.startActivity();
    };

    void getPackageManager() {
        pkms.getPackageManager();
    }

}

class AMS {
    void startActivity() {
        System.out.println("startActivity");
    };
}

class PKMS {
    void getPackageManager() {
        System.out.println("getPackageManager");
    }
}

ContextImpl相当于一个外观模式,Wrapper类是装饰器模式

11、Flyweight(享元)

实际应用:Message的重用,JDK中的String对象的常量池

对象池的一种实现,比如一篇word文档中有一万个字符,创建一万个字符对象代价就太大了。通常和state模式或strategy模式一起使用

12、Proxy(代理)

实际应用:Binder

对于理解Binder机制很有帮助。

public class Proxy {

    public static void main(String[] args) {
        RealSub rs = new RealSub();
        ProxySub ps = new ProxySub(rs);
        ps.visit();
    }
}

abstract class Sub {
    abstract void visit();
}

class RealSub extends Sub {
    @Override
    void visit() {
        System.out.println("RealVisit");
    }
}

class ProxySub extends Sub {
    RealSub sub;

    ProxySub(RealSub sub) {
        this.sub = sub;
    }

    @Override
    void visit() {
        sub.visit();
    }
}

三、行为模式

13、chain of responsibility(责任链)(对象行为)

实际应用:事件分发机制,比如屏幕的触摸事件

要点是当前Handler保持一个下一节点Handler的引用,当前节点处理不了则把消息分发给下一节点。

public class ChainOfResponsibility {

    public static void main(String[] args) {
        Request1 r1 = new Request1();
        Request2 r2 = new Request2();

        Handler1 h1 = new Handler1();
        Handler2 h2 = new Handler2();
        h1.next = h2;
        h1.handlerRequest(r1);
        h1.handlerRequest(r2);
    }

}

abstract class AbsHandler {
    AbsHandler next;

    void handlerRequest(AbsRequest req) {
        if (getHanlderLevel() == req.getRequestLevel()) {
            handle(req);
        } else {
            next.handle(req);
        }
    }

    abstract String getHanlderLevel();

    abstract void handle(AbsRequest req);
}

class Handler1 extends AbsHandler {

    @Override
    String getHanlderLevel() {
        return "1";
    }

    @Override
    void handle(AbsRequest req) {
        System.out.println("Handler1 handle");

    }
}

class Handler2 extends AbsHandler {

    @Override
    String getHanlderLevel() {
        return "2";
    }

    @Override
    void handle(AbsRequest req) {
        System.out.println("Handler2 handle");
    }

}

abstract class AbsRequest {
    abstract String getRequestLevel();
}

class Request1 extends AbsRequest {

    @Override
    String getRequestLevel() {
        return "1";
    }
}

class Request2 extends AbsRequest {

    @Override
    String getRequestLevel() {
        return "2";
    }

}
//output:
Handler1 handle
Handler2 handle

14、command(命令)(对象行为)

实际应用:PackageManagerService中的MeasureParams、InstallParams和MoveParams

通过把请求封装成对象,不同的命令对象子类持有各自的接收者,接受者可以相同也可以不同,然后不同的命令对象中,接收者执行不同的具体操作。

command模式是过程语言中回调(callback)机制的一个面向对象的替代品

public class CommandPattern {

    public static void main(String[] args) {
        Car car = new Car();
        LeftCommand left = new LeftCommand(car);
        RightCommand right = new RightCommand(car);
        BackCommand back = new BackCommand(car);
        ForwardCommand forward = new ForwardCommand(car);

        Handler h = new Handler(car);
        h.setBack(back);
        h.setForward(forward);
        h.setLeft(left);
        h.setRight(right);

        h.toBack();
        h.toLeft();
        h.toForward();
        h.toRight();
		
        h.undo();
        h.undo();
        h.undo();
        h.undo();
    }
}

class Car {

    void toLeft() {
        System.out.println("toLeft");
    }

    void toRight() {
        System.out.println("toRight");
    }

    void toForward() {
        System.out.println("toForward");
    }

    void toBack() {
        System.out.println("toBack");
    }
}

interface Command {
    void execute();
    void undo();
}

class LeftCommand implements Command {
    Car car;

    public LeftCommand(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void execute() {
        car.toLeft();
    }

    @Override
    public void undo() {
        car.toRight();
		
    }
}

class RightCommand implements Command {
    Car car;

    public RightCommand(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void execute() {
        car.toRight();
    }

    @Override
    public void undo() {
        car.toLeft();
		
    }
}

class ForwardCommand implements Command {
    Car car;

    public ForwardCommand(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void execute() {
        car.toForward();
    }

    @Override
    public void undo() {
        car.toBack();
		
    }
}

class BackCommand implements Command {
    Car car;

    public BackCommand(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void execute() {
        car.toBack();
    }

    @Override
    public void undo() {
        car.toForward();
		
    }
}

class Handler {
    Car car;
    LeftCommand left;
    RightCommand right;
    BackCommand back;
    ForwardCommand forward;
    ArrayList<Command> commandList = new ArrayList<>();
    Handler(Car car) {
        this.car = car;
    }

    public void setLeft(LeftCommand left) {
        this.left = left;
    }

    public void setRight(RightCommand right) {
        this.right = right;
    }

    public void setBack(BackCommand back) {
        this.back = back;
    }

    public void setForward(ForwardCommand forward) {
        this.forward = forward;
    }

    void toLeft() {
        left.execute();
        commandList.add(left);
    }

    void toRight() {
        right.execute();
        commandList.add(right);
    }

    void toBack() {
        back.execute();
        commandList.add(back);
    }

    void toForward() {
        forward.execute();
        commandList.add(forward);
    }
	
    void undo(){
        if(commandList.size() > 0){
            commandList.get(commandList.size() - 1).undo();
            commandList.remove(commandList.size() - 1);
        }
    }
}
//output:
toBack
toLeft
toForward
toRight
toLeft
toBack
toRight
toForward

15、interpreter(解释器)(类行为)

实际应用:xml解释器

经常会用到一些正则表达式进行字符串匹配,比较复杂

16、iterator(迭代器)(对象行为)

实际应用:容器对象的遍历

17、mediator(中介者)(对象行为)

实际应用:KeyguardViewMediator

将两个对象直接的操作通过实现一个中介者进行解耦。具体客户类都持有一个中介者对象,中介者持有具体客户类对象。缺点是中介者封装了协议,比任何一个客户类都复杂,业务太多的话会变得难以维护。

public class MediatorPattern {

    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        Owner owner = new Owner(mediator);
        Render render = new Render(mediator);
        System.out.println("mediator has money : " + mediator.money);
        render.action();
        System.out.println("mediator has money : " + mediator.money);
        owner.action();
        System.out.println("mediator has money : " + mediator.money);
    }

}

abstract class Trader {
    Mediator m;

    abstract void action();
}

class Owner extends Trader {

    public Owner(ConcreteMediator m) {
        this.m = m;
    }

    @Override
    void action() {
        m.giveMoney(100);
        System.out.println("Owner receive money from mediator");
    }

}

class Render extends Trader {

    public Render(ConcreteMediator m) {
        this.m = m;
    }

    @Override
    void action() {
        m.receiveMoney(100);
        System.out.println("Render give money to mediator");

    }

}

abstract class Mediator {
    Owner owner;
    Render render;

    abstract void receiveMoney(int money);

    abstract void giveMoney(int money);
}

class ConcreteMediator extends Mediator {
    int money = 0;

    @Override
    void receiveMoney(int money) {
        this.money += money;
    }

    @Override
    void giveMoney(int money) {
        this.money -= money;

    }
}
//output:
mediator has money : 0
Render give money to mediator
mediator has money : 100
Owner receive money from mediator
mediator has money : 0

18、memento(备忘录)(对象行为)

实际应用:onSaveInstanceState(activity相当于caretaker,Bundle相当于memento,各种UI信息相当于originator)

通过实现一个备忘录(memento)对象,保存原发器(originator)的状态,caretaker负责管理memento。

*变量以及状态封装成对象进行保存

19、observer(观察者)(对象行为)

实际应用:ListView

BaseAdapter创建的时候会同时创建一个DataSetObservable(被观察者),当listview调用setAdapter时会创建一个AdapterDataSetObserver(观察者),当Adapter调用notifyDataSetChanged时,被观察者调用notifyChanged遍历通知所有观察者执行onChanged方法,然后观察者会执行重新布局的操作。

public class ObserverPattern {
    public static void main(String[] args) {
        ConcreteObserver osr1 = new ConcreteObserver("osr1");
        ConcreteObserver osr2 = new ConcreteObserver("osr2");
        ConcreteSubject sub = new ConcreteSubject();
        sub.attach(osr1);
        sub.attach(osr2);
        sub.notifyObservers();
    }
}

interface Observer {
    void update(Subject o, String arg);
}

class ConcreteObserver implements Observer {
    String name;

    public ConcreteObserver(String name) {
        super();
        this.name = name;
    }

    @Override
    public void update(Subject o, String arg) {
        System.out.println(name + " receive: " + arg);
    }
}

abstract class Subject {
    abstract void attach(Observer observer);

    abstract void detach(Observer observer);

    abstract void notifyObservers();
}

class ConcreteSubject extends Subject {
    ArrayList<Observer> list = new ArrayList<>();

    @Override
    void attach(Observer observer) {
        list.add(observer);
    }

    @Override
    void detach(Observer observer) {
        list.remove(observer);
    }

    @Override
    void notifyObservers() {
        for (Observer observer : list) {
            observer.update(this, "new content!");
        }
    }
}
//output:
osr1 receive: new content!
osr2 receive: new content!

20、state(状态)(对象行为)

实际应用:WifiStateMachine

状态模式把对象行为包装在不同的状态对象里,意图是让一个对象在内部状态改变的时候行为也跟着改变。

*状态封装成接口

public class State {

    public static void main(String[] args) {
        TvController tvController = new TvController();
        tvController.downVolme();
        tvController.powerOn();
        tvController.downVolme();
        tvController.powerOff();
        tvController.preChannel();
        tvController.powerOn();
        tvController.nextChannel();
    }
}

interface TvState{
    void upVolume();
    void downVolme();
    void nextChannel();
    void preChannel();
}

class PowerOffState implements TvState{

    @Override
    public void upVolume() {
        System.out.println("TV is PowerOff");
    }

    @Override
    public void downVolme() {
        System.out.println("TV is PowerOff");
    }

    @Override
    public void nextChannel() {
        System.out.println("TV is PowerOff");
    }

    @Override
    public void preChannel() {
        System.out.println("TV is PowerOff");
    }
}

class PowerOnState implements TvState{

    @Override
    public void upVolume() {
        System.out.println("upVolume");
    }

    @Override
    public void downVolme() {
        System.out.println("downVolme");
    }

    @Override
    public void nextChannel() {
        System.out.println("nextChannel");
    }

    @Override
    public void preChannel() {
        System.out.println("preChannel");
    }
}

class TvController implements TvState{
    TvState tvState = new PowerOffState();;
    public void powerOn(){
        tvState = new PowerOnState();
        System.out.println("PowerOn TV!");
    }
	
    public void powerOff(){
        tvState = new PowerOffState();
        System.out.println("PowerOff TV!");
    }

    @Override
    public void upVolume() {
        tvState.upVolume();
    }

    @Override
    public void downVolme() {
        tvState.downVolme();
    }

    @Override
    public void nextChannel() {
        tvState.nextChannel();
    }

    @Override
    public void preChannel() {
        tvState.preChannel();
    }
}
//output:
TV is PowerOff
PowerOn TV!
downVolme
PowerOff TV!
TV is PowerOff
PowerOn TV!
nextChannel

21、strategy(策略)(对象行为)

实际应用:ImageLoader中的各种MemoryCache算法,android实现动画效果的各种插值器算法。

对算法进行封装,让各个算法直接可以相互替换。

*方法封装成对象

22、template method(模板方法)(类行为)

实际应用:asyncTask,Activity(生命周期方法)

定义一个算法框架,让其实现延迟到子类。

23、visitor(访问者)(对象行为)

实际应用:注解框架的实现(ButterKnife)

是为了将数据操作与数据结构分离的模式。

public class VisitorPattern {

    public static void main(String[] args) {
        Report report = new Report();
        report.showReport(new VisitorA());
        System.out.println("----------------");
        report.showReport(new VisitorB());
    }
}

abstract class Staff {
    String name;
    String sex;

    public Staff(String name, String sex) {
        super();
        this.name = name;
        this.sex = sex;
    }

    abstract void accept(Visitor visitor);
}

class StaffA extends Staff {

    public StaffA(String name, String sex) {
        super(name, sex);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitStaffA(this);
    }
}

class StaffB extends Staff {

    public StaffB(String name, String sex) {
        super(name, sex);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitStaffB(this);
    }
}

interface Visitor {
    void visitStaffA(StaffA staffA);

    void visitStaffB(StaffB staffB);
}

class VisitorA implements Visitor {

    @Override
    public void visitStaffA(StaffA staffA) {
        System.out.println(staffA.name);
    }

    @Override
    public void visitStaffB(StaffB staffB) {
        System.out.println(staffB.name);
    }
}

class VisitorB implements Visitor {

    @Override
    public void visitStaffA(StaffA staffA) {
        System.out.println(staffA.sex);
    }

    @Override
    public void visitStaffB(StaffB staffB) {
        System.out.println(staffB.sex);
    }
}

class Report {
    List<Staff> list = new ArrayList<Staff>();

    public Report() {
        list.add(new StaffA("AA", "MALE"));
        list.add(new StaffA("AB", "FEMALE"));
        list.add(new StaffB("BA", "MALE"));
        list.add(new StaffB("BB", "FEMALE"));
    }

    public void showReport(Visitor visitor) {
        for (Staff staff : list) {
            staff.accept(visitor);
        }
    }
}
//output:
A
A
B
B
----------------
MALE
FEMALE
MALE
FEMALE