logo头像

我有一个梦想

设计模式

本文于 909 天之前发表,文中内容可能已经过时。

[TOC]

单例模式

定义

确保某个类中只有一个实例,而且子性实例化并向整个系统提供整个实例

例子

饿汉:
1
2
3
4
5
6
7
8
9
public class Singleton {
//在静态初始化器中创建单例实例,这段代码保证了线程安全
private static final Singleton instance = new Singleton();
//Singleton类只有一个构造方法并且是被private修饰的,所以用户无法通过new方法创建该对象实例
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
懒汉:
1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private static Singleton instance;
private Singleton (){}
//没有加入synchronized关键字的版本是线程不安全的
public static synchronized Singleton getInstance() {
//判断当前单例是否已经存在,若存在则返回,不存在则再建立单例
if (instance == null) {
instance = new Singleton();
}
return instance;
}
双重校验锁(DCL):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
private static volatile Singleton instance;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
  1. 双重判断的原因?
    • 第一个判断减少锁的使用,提升性能
    • 多个线程同时等待锁,当第一个创建后,就不需要其他线程重复重建
  2. volatile的理解
    • 禁止重排序导致instance获取失败。
      • 给Singleton的实例分配内存
      • 调用构造函数,初始化成员
      • 将instance对象指向分配的内存空间

        执行顺序有可能是1-2-3,1-3-2

如果是1-3-2,new Singleton()方法执行时可能导致分配了空间,并指向了内存空间,但是没有赋值,这样另一个线程拿到后会导致出错

缺点:部分情况下,这种单例模式会失效

静态内部类:
1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
private Singleton() { }
public static Singleton getInstance() {
return SingletonHolder.instance;
}
/**
* 静态内部类
*/
private static class SingletonHolder{
private static final Singleton instance = new Singleton();
}
}

首次加载Singleton不会初始化instance,当调用getInstance方法时,初始化SingletonHolder类,这样虚拟机加载该类是线程安全的,保证单例对象的唯一性

枚举单例
1
2
3
4
5
6
public enum SingletonEnum{
INSTANCE;
public void doSomething(){
......
}
}

注意:在反序列化时,会重新创建对象,不符合单例

容器单例
1
2
3
4
5
6
7
8
9
10
11
12
public class SingletonManager{
private static Map<String,Object> objMap = new HashMap<>();
private SingletonManager(){}
public static void registerService(String key,Object instance){
if(!objMap.containsKey(key)){
objMap.put(key,instance);
}
}
public static Object getValue(String key){
return objMap.get(Key);
}
}

对单例内容统一管理,放置在map中,但是HashMap线程不安全,所以最好使用ConcurrentHashMap,管理多个单例类

源码应用

  1. LayoutInflater.from(context)
  • 进入main函数
  • 新建ActivityThread,调用attach函数
  • AMS通信最终调用ahndlelauncherActivity
  • 创建Activity
  • 创建Application
  • 获取Context对象
  • 将context对象attach到activity中
  • 调用Activity的onCreate方法

在虚拟机第一次加载ContextImpl时会注册LayoutInflater Service,将这些服务存储在HashMap中,下次直接从缓存中读取,应用的是容器单例形式。

  1. 深入LayoutInflater
    LayoutInflater是抽象类,具体实现类是PhoneLayoutInflater

inflate方法:

  • 解析xml根标签(父布局)
  • 判断merge,如果是merge直接将子布局添加到根布局
  • 如果是普通标签,调用createViewFromTag对该元素进行解析
  • 解析所有子view,将这些子view都添加到根布局temp下
  • 返回解析到根视图

q:为什么自定义view要使用全包名,而内置view(TextView)就不用?

a:因为在布局加载过程中,如果是内置view,直接执行onCreateView方法创建view,并将“android.widget.”加在内置view前(android.widget.TextView),然后执行createView方法。如果是自定义view,从xml中获取全量包名直接执行createView方法即可,默认前缀为null

inflate通过深度优先遍历来构造视图树

优缺点

优点:

  1. 减少内存开支,避免创建和销毁的性能损耗
  2. 减少性能开销,永久驻留内存方式初始化复杂对象和依赖
  3. 避免对同一资源的多重占用,例如-个写文件操作,只有一个实例可以写,避免对这一个资源文件的同时写操作(避免线程不安全)
  4. 设置全局访问点,优化和共享资源访问,便于管理

缺点:

  1. 拓展困难,只能修改代码
  2. 如果持有context对象,会造成内存泄漏

建造者模式

例子

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

核心思想是添加建造者构建主类,减少主类功能,建造者只负责构建主类

简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class Computer {
//显示器
String display;
//cpu型号
String cpu;
//主板型号
String mainBoard;
//显卡型号
String gpu;

public Computer(Builder builder) {
this.display = builder.display;
this.cpu = builder.cpu;
this.mainBoard = builder.mainBoard;
this.gpu = builder.gpu;
}

@Override
public String toString() {
return "显示器是" + display + "\ncpu是" + cpu + "\n主板是" + mainBoard + "\n显卡是" + gpu;
}

static class Builder{
//显示器
String display;
//cpu型号
String cpu;
//主板型号
String mainBoard;
//显卡型号
String gpu;

public Builder(){
this.display = "三星曲屏";
this.cpu = "i5 8400";
this.mainBoard = "华硕Z360-B";
this.gpu = "GTX 1050Ti";
}

public Builder setDisplay(String display) {
this.display = display;
return this;
}

public Builder setcpu(String cpu) {
this.cpu = cpu;
return this;
}

public Builder setMainBoard(String mainBoard) {
this.mainBoard = mainBoard;
return this;
}

public Builder setGpu(String gpu) {
this.gpu = gpu;
return this;
}

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

public static void main(String args[]){
Computer computer = new Computer.Builder()
.setcpu("i9 4700u")
.setGpu("GTX 2060Ti")
.setMainBoard("华硕Z480")
.build();
System.out.println(computer.toString());
}
}

源码应用

  1. AlertDialog
    内部调用Buidler模式构建,最终通过WindowManager显示在手机屏幕上。

  2. WindowManager源码分析
    所有需要显示到屏幕上的内容都是通过WindowManager来操作的,WM的一个非常重要的子系统为WMS(WindowManagerService)
    在android.app.SystemServiceRegistry中:

1
2
3
4
5
6
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});

WMS也是初始化的众多服务的一种,所以在ContentImpl中初始化,并将初始化的服务注册到一个map中,需要时通过键获取调用,属于单例模式的容器单例。

以PopupWindow为例,我们获取到popupWindow的初始化:

1
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

通过以上方法获取WM,显示时使用showAtLocation()方法,
1
2
3
4
5
6
7
8
9
10
11
public void showAtLocation(IBinder token, int gravity, int x, int y) {
......
invokePopup(p);
}

private void invokePopup(WindowManager.LayoutParams p) {
......
mWindowManager.addView(decorView, p);
......
}

通过一系列的调用,最终使用WM的addView方法添加布局,回溯之前的分析WM的实例是WindowManagerImpl,进入addView方法

1
2
3
4
5
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

而在WMImpl方法中调用WMGlobal.addView方法,进入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......

ViewRootImpl root;
View panelParentView = null;

......
//构建ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
//view设置参数
view.setLayoutParams(wparams);

//将view添加到列表
mViews.add(view);
//将ViewRootImpl添加到列表
mRoots.add(root);
//将参数添加在列表
mParams.add(wparams);

// do this last because it fires off messages to start doingthings
try {
//调用viewRootImpl的setView方法添加布局
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}

  • 构建ViewRootImpl
  • 将布局参数设置给view
  • 存储ViewRootImpl、View、LayoutParam到列表
  • 调用ViewRootImpl.setView将view显示在窗口

进一步查看ViewRootImpl是什么?

1
2
3
4
5
6
7
8
9
public ViewRootImpl(Context context, Display display) {
mContext = context;
//获取WindowSession,也就是和WMS建立连接
mWindowSession = WindowManagerGlobal.getWindowSession();
......
//创建线程为当前线程,因为主界面在UI线程,所以在子线程更新UI会抛出异常,但并不是只用UI线程才能更新UI
mThread = Thread.currentThread();
......
}

进入WMGlobal.getWindowSession方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
//获取WMS
IWindowManager windowManager = getWindowManagerService();
//建立一个WindowSession
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}

进入getWindowManagerService,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
if (sWindowManagerService != null) {
ValueAnimator.setDurationScale(
sWindowManagerService.getCurrentAnimatorScale());
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
}
}

通过ServiceManager.getService()获取WMS,
1
2
3
4
5
6
7
8
9
10
11
12
13
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}

通过sCache获取到一个IBinder对象,所以FrameWork与WMS之间也是通过Binder机制进行通信的,回溯到之前,会调用IWindowManager.Stub.asInterface(),将IBinder对象转化为WM对象,然后通过openSession与WMS建立通信绘画,之后通过这个session进行交换信息,但是到现在还是没有显示view,所以继续走ViewRootImpl.setView方法,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
......
//请求布局
requestLayout();
......
try {
//通过Windowsession和WMS通信,请求显示
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
}
}
}

  • requestlayout:请求布局
  • 向WMS请求显示布局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
//线程校验
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}

void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
//开启屏障消息,优先处理
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//通过handler回调执行MTraversalRunnable
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}

通过handler回调执行MTraversalRunnable,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}

void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
//view的具体操作
performTraversals();

if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}

最终进入performTraversals进行具体操作

  1. 获取Surface对象,用于图形绘制
  2. performMeasure函数,测量整个视图树各个view的大小
  3. performLayout,布局整个view
  4. performDraw,绘制整个view

优缺点

优点:

  • 良好的封装性,使客户端不知道产品内部组成细节
  • 独立,容易拓展

缺点:

  • 产生多余Builder对象和Director对象,消耗内存

原型模式

定义

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象

简单例子

深拷贝和浅拷贝

原型模式实际上是浅拷贝,也称为影子拷贝。拷贝实际不是将所有字段重新构造一份,而是拷贝文档的字段引用原始文档的字段而已,所以会导致修改副本的字段,原始字段也会跟着修改,因为最终修改的是同一个内存单元,所以在原型模式中,要尽量使用深拷贝。

  • 深拷贝:复制引用对象的值
  • 浅拷贝:复制引用

源码分析

  1. ArrayList的clone方法实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public Object clone() {
    try {
    //克隆自身
    ArrayList<?> v = (ArrayList<?>) super.clone();
    //克隆数组对象
    v.elementData = Arrays.copyOf(elementData, size);
    v.modCount = 0;
    return v;
    } catch (CloneNotSupportedException e) {
    // this shouldn't happen, since we are Cloneable
    throw new InternalError(e);
    }
    }

    克隆自身后,在克隆数组对象,并没有对size进行克隆是因为size是值类型,并不是引用类型。

  2. Intent的clone方法分析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    @Override
    public Object clone() {
    return new Intent(this);
    }

    public Intent(Intent o) {
    this(o, COPY_MODE_ALL);
    }

    private Intent(Intent o, @CopyMode int copyMode) {
    this.mAction = o.mAction;
    this.mData = o.mData;
    this.mType = o.mType;
    this.mPackage = o.mPackage;
    this.mComponent = o.mComponent;

    if (o.mCategories != null) {
    this.mCategories = new ArraySet<>(o.mCategories);
    }

    if (copyMode != COPY_MODE_FILTER) {
    this.mFlags = o.mFlags;
    this.mContentUserHint = o.mContentUserHint;
    this.mLaunchToken = o.mLaunchToken;
    if (o.mSourceBounds != null) {
    this.mSourceBounds = new Rect(o.mSourceBounds);
    }
    if (o.mSelector != null) {
    this.mSelector = new Intent(o.mSelector);
    }

    if (copyMode != COPY_MODE_HISTORY) {
    if (o.mExtras != null) {
    this.mExtras = new Bundle(o.mExtras);
    }
    if (o.mClipData != null) {
    this.mClipData = new ClipData(o.mClipData);
    }
    } else {
    if (o.mExtras != null && !o.mExtras.maybeIsEmpty()) {
    this.mExtras = Bundle.STRIPPED;
    }

    // Also set "stripped" clip data when we ever log mClipData in the (broadcast)
    // history.
    }
    }
    }

在Intent的clone方法中直接使用new方法构建了新intent

所以延伸出一个问题,new和clone怎么选择?

如果对象的构造成本太高或者构造比较麻烦,那么使用clone函数效率高,否则使用new

  1. intent的查找和匹配

intent是怎么查找对应的组件然后跳转的呢?

在ContextImpl初始化的SystemServiceRegistry中初始化各种服务(WMS,AMS等),其中,初始化了PMS(PackageManagerService)

在ContextImpl中执行getPackageManager方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}

IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}

return null;
}

进入ActivityThread.getPackageManager()
1
2
3
4
5
6
7
8
9
10
11
12
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
//获取PackageManagerService
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b);
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}

获取到PackageManagerService服务,这个服务是在系统初始化时通过SystemServer启动的,现在只是获取,查看PackageManagerService类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//PMS为IPackageManager.Stub的具体实现类
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {
// Collect privileged system packages.
// 扫描特殊系统包
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRIVILEGED,
0);

// Collect ordinary system packages.
// 扫描普通系统包
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM,
0);

// Collect privileged vendor packages.
// 扫描特殊vendor下包
File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedVendorAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR
| SCAN_AS_PRIVILEGED,
0);

// Collect ordinary vendor packages.
// 扫描普通vendor下包
File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(vendorAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);

// Collect privileged odm packages. /odm is another vendor partition
// other than /vendor.
// 扫描特殊odm下包/odm时vendor的一部分
File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
"priv-app");
try {
privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedOdmAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR
| SCAN_AS_PRIVILEGED,
0);

// Collect ordinary odm packages. /odm is another vendor partition
// other than /vendor.
// 扫描普通odm下包/odm时vendor的一部分
File odmAppDir = new File(Environment.getOdmDirectory(), "app");
try {
odmAppDir = odmAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(odmAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);

// Collect all OEM packages.
// 扫描所有OEM包
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM,
0);

// Collected privileged product packages.
// 扫描特殊product包
File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
try {
privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(privilegedProductAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT
| SCAN_AS_PRIVILEGED,
0);

// Collect ordinary product packages.
// 扫描普通product包
File productAppDir = new File(Environment.getProductDirectory(), "app");
try {
productAppDir = productAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(productAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
}
}

PMS会加载一系列,在不同目录下的包执行scanDirTracedLI方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + dir.getAbsolutePath() + "]");
try {
scanDirLI(dir, parseFlags, scanFlags, currentTime);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}

private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
//获取目录下所有文件
final File[] files = dir.listFiles();
......
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
......
for (; fileCount > 0; fileCount--) {
scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
currentTime, null);
}
......
}
}

扫描目录下的子目录,对apk文件进行解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public void submit(File scanFile, int parseFlags) {
mService.submit(() -> {
ParseResult pr = new ParseResult();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
try {
//创建一个包解析器
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
//执行apk包解析
pr.pkg = parsePackage(pp, scanFile, parseFlags);
} catch (Throwable e) {
pr.throwable = e;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
mQueue.put(pr);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// Propagate result to callers of take().
// This is helpful to prevent main thread from getting stuck waiting on
// ParallelPackageParser to finish in case of interruption
mInterruptedInThread = Thread.currentThread().getName();
}
});
}

@VisibleForTesting
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
int parseFlags) throws PackageParser.PackageParserException {
return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}

创建一个PackageParser,调用parsePackage函数解析apk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
if (parsed != null) {
return parsed;
}
//如果是文件夹类型
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);
} else {
//解析单个apk
parsed = parseMonolithicPackage(packageFile, flags);
}

cacheResult(packageFile, flags, parsed);

return parsed;
}

如果是文件夹类型,加载多个apk文件,如果是单个apk,只加载一个apk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final AssetManager assets = newConfiguredAssetManager();
final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
if (mOnlyCoreApps) {
if (!lite.coreApp) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Not a coreApp: " + apkFile);
}
}

try {
//执行具体解析
final Package pkg = parseBaseApk(apkFile, assets, flags);
pkg.setCodePath(apkFile.getAbsolutePath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assets);
}
}

进入parseBaseApk:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
//获取apk路径
final String apkPath = apkFile.getAbsolutePath();

String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}

mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();

if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);

final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);

Resources res = null;
XmlResourceParser parser = null;
try {
//获取apk资源文件
res = new Resources(assets, mMetrics, null);
//解析AndroidManifest
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

final String[] outError = new String[1];
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}

pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSignatures(null);

return pkg;
......
}

获取apk路径,解析apk资源文件及AndroidManifest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
int flags, String[] outError) throws XmlPullParserException, IOException {
//创建package对象,将版本信息存储进来
// Go ahead and parse the child
Package childPkg = new Package(childPackageName);

// Child package inherits parent version code/name/target SDK
childPkg.mVersionCode = parentPkg.mVersionCode;
childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
childPkg.mVersionName = parentPkg.mVersionName;
childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;

childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
if (childPkg == null) {
// If we got null then error was set during child parsing
return false;
}

// Set the parent-child relation
if (parentPkg.childPackages == null) {
parentPkg.childPackages = new ArrayList<>();
}
parentPkg.childPackages.add(childPkg);
childPkg.parentPackage = parentPkg;

return true;
}

创建package对象,将版本信息存储进来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
.......
//解析AndroidManifest的深度
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
......
if (tagName.equals(TAG_APPLICATION)) {
......
//解析Application标签
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
} else if (tagName.equals(TAG_PERMISSION)) {
//解析权限标签
if (!parsePermission(pkg, res, parser, outError)) {
return null;
}
}
return pkg;
}

获取AndroidManifest的深度,然后深度遍历获取所有的标签并依次处理,这里以Application为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
//获取应用信息
final ApplicationInfo ai = owner.applicationInfo;
//获取包名
final String pkgName = owner.applicationInfo.packageName;
//获取Application的TypedArray
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
......
//获取应用名
String manageSpaceActivity = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
Configuration.NATIVE_CONFIG_VERSION);
......
//获取Application的allowBackUp
boolean allowBackup = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
//获取主题
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
//获取描述
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);

//获取taskAffinity
ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
str, outError);

final int innerDepth = parser.getDepth();
int type;
//迭代Application元素下的所有子元素
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
//获取标签名
String tagName = parser.getName();
//如果是Activity
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.activities.add(a);
//如果是receiver
} else if (tagName.equals("receiver")) {
Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.receivers.add(a);

}
}

return true;
}

解析Application的其他属性及其子标签,而后返回方法直到scanDirLI方法,执行scanPackageLI函数

scanPackageLI—>scanPackageInternalLI—>scanPackageLI—>scanPackageDirtyLI—>commitPackageSettings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting,
UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
......
//获取activities的大小
N = pkg.activities.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName);
//将activity添加到mActivies
mActivities.addActivity(a, "activity");
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
//其他标签忽略
......
}

将解析的标签,例activity记载到PMS的缓存中。至此,apk的所有信息就被存储在系统中,当使用intent跳转时会在该信息表中进行查找,然后跳转。

我们使用intent时,一般是这样:

1
2
Intent intent = new Intent(this,MainActivity.class);
this.startActivity(intent);

跟踪源码,最终跳转到startActivityForResult:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//启动Activity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
//发送启动请求
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}

cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}

通过instrumentation启动Activity,并向主线程发送启动请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
......
try {
//将Intent中的数据迁移到粘贴板
intent.migrateExtraStreamToClipData();
//准备离开当前进程
intent.prepareToLeaveProcess(who);
//通过AMS启动Activity
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
//检测结果,并且回调给调用端
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}

进入AMS方法,调用

startActivityAsUser—>ActivityStarter.startActivityMayWait—>ActivityStackSupervisor.resolveIntent—>AMS.getPackageManagerInternalLocked—>PMS.resolveIntent—>PMS.resolveIntentInternal—>PMS.queryIntentActivitiesInternal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int filterCallingUid, int userId,
boolean resolveForStart) {
......
//获取包名
final String pkgName = intent.getPackage();
//获取component对象
ComponentName comp = intent.getComponent();
//如果component不为null
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
//直接getActivityInfo获取ActivityInfo对象
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
......
}
......
//如果是隐式intent
synchronized (mPackages) {
//如果包名为null
if (pkgName == null) {
List<CrossProfileIntentFilter> matchingFilters =
getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
// Check for results that need to skip the current profile.
//获取resolveInfo对象
ResolveInfo xpResolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
resolvedType, flags, userId);
if (xpResolveInfo != null) {
List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
xpResult.add(xpResolveInfo);
return applyPostResolutionFilter(
filterIfNotSystemUser(xpResult, userId), instantAppPkgName);
}
} else {
//通过包名获取Package对象
final PackageParser.Package pkg = mPackages.get(pkgName);
result = null;
if (pkg != null) {
//通过package获取ActivityInfo
result = filterIfNotSystemUser(
mActivities.queryIntentForPackage(
intent, resolvedType, flags, pkg.activities, userId),
userId);
}
......
}

如果intent指明了Component(即MainActivity),直接获取到ActivityInfo并且数量只有一个,直接返回。如果Component为空,会检测发起方所在的包名,如果有包名,通过包名获取ActivityInfo,反之,根据其他信息比如外部拉起,action,Category等判断。

总结:在系统启动时,PMS启动分析所有apk的信息,创建一个信息表,当用胡使用Intent跳转时,会根据intent中包含的信息到PMS的信息表查找,最后跳转到目标组件

优缺点

优点:

  • 内存中二进制流的拷贝,其比直接new一个对象性能会好很多
    缺点:
  • 直接在内存中拷贝,不会执行构造函数,使用过程中对比new和clone方法的区别

原型模式就是要实现深拷贝

工厂模式

定义

用于创建对象的接口,让子类决定实例化那个类,解决对象之间的解耦

例子

简单工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public abstract class Product {
/**
* 子类具体实现方法
*/
public abstract void method();
}

public class ProductA extends Product {
@Override
public void method() {
System.out.println("制造ProductA");
}
}

public class ProductB extends Product {
@Override
public void method() {
System.out.println("制造ProductB");
}
}

public class Factory {
public Product create(String type){
if("A".equals(type)){
return new ProductA();
}else if("B".equals(type)){
return new ProductB();
}else{
return null;
}
}
}

public static void main(String args[]) {
Factory factory = new Factory();
Product a = factory.create("A");
a.method();
Product b = factory.create("B");
b.method();
}

运行后:

制造ProductA

制造ProductB

工厂方法抽象

产品类不变,工厂变为抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public abstract class Factory {
/**
* 工厂具体实现方法
* @return
*/
public abstract Product create();
}

public class FactoryA extends Factory {
@Override
public Product create() {
return new ProductA();
}
}

public class FactoryB extends Factory {
@Override
public Product create() {
return new ProductB();
}
}

public static void main(String args[]) {
FactoryA factoryA = new FactoryA();
FactoryB factoryB = new FactoryB();
factoryA.create().method();
factoryB.create().method();
}

运行后:

制造ProductA

制造ProductB

抽象工厂

需要多个产品最终组成为一个产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public abstract class Cpu {
/**
* cpu子类的具体执行
*/
public abstract void method();
}

public class CpuA extends Cpu {
@Override
public void method() {
System.out.println("A型号CPU");
}
}

public class CpuB extends Cpu {
@Override
public void method() {
System.out.println("B型号CPU");
}
}

public abstract class Display {
/**
* 显示屏的子类执行方法
*/
public abstract void method();
}

public class DisplayA extends Display {
@Override
public void method() {
System.out.println("A型号显示屏");
}
}

public class DisplayB extends Display {
@Override
public void method() {
System.out.println("B型号显示屏");
}
}

public abstract class Factory {
/**
* 创建Cpu
* @return
*/
public abstract Cpu createCpu();

/**
* 创建显示屏
* @return
*/
public abstract Display createDisplay();
}

public class FactoryA extends Factory {

@Override
public Cpu createCpu() {
return new CpuA();
}

@Override
public Display createDisplay() {
return new DisplayA();
}
}

public class FactoryB extends Factory {

@Override
public Cpu createCpu() {
return new CpuB();
}

@Override
public Display createDisplay() {
return new DisplayB();
}
}

public static void main(String args[]) {
FactoryA factoryA = new FactoryA();
FactoryB factoryB = new FactoryB();
factoryA.createCpu().method();
factoryA.createDisplay().method();
factoryB.createCpu().method();
factoryB.createDisplay().method();
}

执行结果如下:

A型号CPU

A型号显示屏

B型号CPU

B型号显示屏

抽象工厂的核心是复杂的工厂模式。存在多个工厂,多种产品类型,就会使用抽象工厂,在android源码中使用较少,并没有那么多产品种类,大部分使用简单工厂或者工厂方法就可以解决。

源码分析

  1. ArrayList和HashSet都继承自Collection接口,collection接口继承自Iterator接口。
  2. xxxActivity都继承自Activity,其onCreate方法就是工厂方法,两个Activity构建不同的view,可以将view看成product,Activity为Factory。
  3. xxService都继承自Service,其onBind方法也可以看作是一个工厂方法
    4.

优缺点

优点:

  • 功能逻辑解耦

缺点:

  • 拓展新功能需要添加新类,复杂类结构

抽象工厂的优点:

  • 分离接口与实现,使用方不知道具体的实现是什么,同时使抽象该工厂方法模式在切换产品类时更加灵活,容易

抽象工厂的缺点:

  • 类文件结构复杂
  • 不容易拓展新类

策略模式

定义

定义一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,策略模式让算法独立于使用他们的客户而独立存在,解决if-else滥用的问题

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class CalculatePrice {

public enum TransPortType {
BUS,
SUBWAY
}

/**
* 计算公交车车费
*/
private void calculateBus(int km) {
System.out.println("公交车" + km + "公里的车票");
}

/**
* 计算地铁车费
*/
private void calculateSubWay(int km) {
System.out.println("地铁" + km + "公里的车票");
}

private void calculate(int km, TransPortType transPortType) {
switch (transPortType) {
case BUS:
calculateBus(km);
break;
case SUBWAY:
calculateSubWay(km);
break;
default:
break;
}
}

public static void main(String args[]){
CalculatePrice calculatePrice = new CalculatePrice();
calculatePrice.calculate(16,TransPortType.BUS);
calculatePrice.calculate(15,TransPortType.SUBWAY);
}
}

结果:
公交车16公里的车票

地铁15公里的车票

当需要拓展时,比如多了一个出租车,需要这样做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class CalculatePrice {

public enum TransPortType {
BUS,
SUBWAY,
TAXI
}

/**
* 计算公交车车费
*/
private void calculateBus(int km) {
System.out.println("公交车" + km + "公里的车票");
}

/**
* 计算地铁车费
*/
private void calculateSubWay(int km) {
System.out.println("地铁" + km + "公里的车票");
}

/**
* 计算出租车车费
*/
private void calculateTaxi(int km) {
System.out.println("出租车" + km + "公里的车票");
}

private void calculate(int km, TransPortType transPortType) {
switch (transPortType) {
case BUS:
calculateBus(km);
break;
case SUBWAY:
calculateSubWay(km);
break;
case TAXI:
calculateTaxi(km);
break;
default:
break;
}
}

public static void main(String args[]){
CalculatePrice calculatePrice = new CalculatePrice();
calculatePrice.calculate(16,TransPortType.BUS);
calculatePrice.calculate(15,TransPortType.SUBWAY);
calculatePrice.calculate(17,TransPortType.TAXI);
}
}

结果:

公交车16公里的车票

地铁15公里的车票

出租车17公里的车票

改动还是比较大的,对源代码的基础上做了更改,并且添加了if-else判断taxi类型。
如果把他改成策略模式,试试效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public abstract class CalculateStrategy {
/**
* 子类具体执行车票计算
*/
public abstract void getPrice(int km);
}

public class BusCalculateStrategy extends CalculateStrategy {
@Override
public void getPrice(int km) {
System.out.println("公交车" + km + "公里的车票");
}
}

public class SubWayCalculateStrategy extends CalculateStrategy {
@Override
public void getPrice(int km) {
System.out.println("地铁" + km + "公里的车票");
}
}

public static void main(String args[]){
CalculateStrategy calculateStrategy = new BusCalculateStrategy();
calculateStrategy.getPrice(16);
CalculateStrategy calculateStrategy1 = new SubWayCalculateStrategy();
calculateStrategy1.getPrice(15);
}

结果:

公交车16公里的车票

地铁15公里的车票

当需要拓展出租车时

1
2
3
4
5
6
7
8
9
10
11
public class TaxiCalculateStrategy extends CalculateStrategy {
@Override
public void getPrice(int km) {
System.out.println("出租车" + km + "公里的车票");
}
}

public static void main(String args[]){
CalculateStrategy calculateStrategy2 = new TaxiCalculateStrategy();
calculateStrategy2.getPrice(17);
}

只需要添加Taxi类继承自策略类,执行具体车费计算方法,在main中调用即可,这样对代码的侵入性最小,不用修改原有逻辑代码,在咋付逻辑出引用效果优秀

状态模式

定义

当一个对象的内在行为改变时,允许改变其行为,整个对象看起来像是改变了其类

源码解析

  1. wifi状态管理

    责任链模式

    定义

    使多个对象都有机会处理请求,这些对象形成一条链,依次执行,直到结束。

    源码解析

  2. view的事件传递

观察者模式

定义

定义对象间一种一对多的一栏关系,使得每当一个对象改变状态,则所有依赖与他的对象都会得到通知并被自动更新

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class Mode2 {
static public interface IObserver {
void update(int temp);
}

static public interface IObservable {
void register(IObserver iObserver);

void unregister(IObserver iObserver);

void notifyObserver();
}

//被观察者(发布者)
static class Observable implements IObservable {
private ArrayList<IObserver> list = new ArrayList<>();
private int temp;

@Override
public void register(IObserver iObserver) {
list.add(iObserver);
}

@Override
public void unregister(IObserver iObserver) {
list.remove(iObserver);
}

@Override
public void notifyObserver() {
for (int i = 0; i < list.size(); i++) {
list.get(i).update(temp);
}
}

public void setTemp(int temp) {
this.temp = temp;
}
}

//观察者1(订阅者)
static class Observer1 implements IObserver {

@Override
public void update(int temp) {
System.out.println("Observable1更新为 = " + temp);
}
}

//观察者2(订阅者)
static class Observer2 implements IObserver {
@Override
public void update(int temp) {
System.out.println("Observable2更新为 = " + temp);
}
}

public static void main(String args[]){
Observable observable = new Observable();
Observer1 observer1 = new Observer1();
Observer2 observer2 = new Observer2();
observable.register(observer1);
observable.register(observer2);
observable.setTemp(32131232);
observable.notifyObserver();
}
}