从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