作者:奔跑中的蜗牛666

装饰者模式

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

在架构设计时,应多用组合,少用继承,同时对扩展开放,对修改关闭

利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

context类图如下:

Android 源码与设计模式_android

Context(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

ContextImpl(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。

ContextWrapper(抽象装饰类):它也是抽象构件类的子类,抽象装饰类不一定是抽象方法。用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

Service,Application(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

在startActivity时候,会调用系统的handleLaunchActivity方法,接着调用performLaunchActivity方法。其中会创建一个ContextImpl. 然后activity.attach(ContextImpl)将ContextImpl赋予ContextWrapper的mBase。ContextWrapper中的所有行为全都通过mBase去实现。同时ContextWrapper通过具体的子类扩展方法不同的行为,实现对context的装饰和功能扩展。

这种组合的方式,避免了继承带来的臃肿结构和属性继承,同时方便扩展和开放

/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context. Can be subclassed to modify behavior without changing
* the original Context.
*/
public class ContextWrapper extends Context{}

源码中对ContextWrapper注释也解释了用装饰者模式的原因。ContextWrapper的子类可以在不改变context原始结构的基础上对context进行功能扩展

代理模式

为其他对象提供一种代理以控制这个对象的访问,代理模式分为静态代理和动态代理。

静态代理:


  • 静态代理如果接口新增一个方法,除了所有实现类(真实主题类)需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
  • 静态代理只能服务于某个特定的对象,不够灵活,代码维护升级成本高。

动态代理


  • 可以通过一个代理类完成全部的代理功能,接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(​​InvocationHandler.invoke​​)。当接口方法数量较多时,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
  • 动态代理的应用使我们的类职责更加单一,复用性更强
  • 不能对类进行代理,只能对接口进行代理,如果我们的类没有实现任何接口,那么就不能使用这种方式进行动态代理(所以用动态代理可能会容易出现类型转换错误的崩溃)。

Android在源码中也大量使用了代理模式:如ActivityManagerProxy。

Android 源码与设计模式_java_02

retrofit中大量使用动态代理。

public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();

@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}

以一个基本的请求举例子: 动态代理只能代理接口,所以要先定义一个请求接口:

public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}

然后是发送具体请求:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();

GitHubService service = retrofit.create(GitHubService.class);

Call<List<Repo>> repos = service.listRepos("octocat");

​Proxy.newProxyInstance​​​最终会调用一个 native 方法,动态生成一个 ​​GitHubService​​(我们前文声明的接口)的实现类。大致如下

public final class $Proxy0 extends Proxy implements GitHubService {  
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });

m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);

m3 = Class.forName("***.GitHubService").getMethod("request",
new Class[0]);

m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);

} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}

public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}

@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

public final void listRepos() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}

Java 帮我们生成的类中重写了我们​​GithubService​​​接口的​​listRepos()​​​,该方法中会调用​​super.h.invoke(this, m3, null);​​​,就是调用父类的​​h​​​的​​invoke()​​​,它的父类是​​Proxy​​​,​​h​​​是一个​​InvocationHandler​​对象,也就是代理中的new InvocationHandler(){}。 通过这种动态代理的方式,封装接口请求,同时也方便统一管理和扩展

模版方法

定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。


  • 提高代码复用性,去除子类中的重复代码。
  • 提高扩展性,不同实现细节放到不同子类中,易于增加新行为。
  • 每个不同的实现都需要定义一个子类,这会导致类的个数的增加

Android中view的绘制流程就使用了设计模式。在父类中定义好具体要执行的类的方法。然后子类根据具体的需要去选择具体的实现

public class View{
//钩子方法,空实现
protected void onDraw(Canvas canvas) {
}
//钩子方法,空实现
protected void dispatchDraw(Canvas canvas) {
}
//绘制方法,定义绘制流程
public void draw(Canvas canvas) {
//其他代码略

/*
* 绘制流程如下:
*
* 1\. 绘制view背景
* 2\. 如果有需要,就保存图层
* 3\. 绘制view内容
* 4\. 绘制子View
* 5\. 如果有必要,绘制渐变框和恢复图层
* 6\. 绘制装饰(滑动条等)
*/

if (!dirtyOpaque) {
drawBackground(canvas);//步骤1\. 绘制view背景
}

// 如果可能的话跳过第2步和第5步(常见情况)
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
if (!dirtyOpaque) onDraw(canvas);//步骤3\. 绘制view内容

dispatchDraw(canvas);//步骤4\. 绘制子View

// 覆盖一部分内容,绘制前景
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}

onDrawForeground(canvas); //步骤6\. 绘制装饰(滑动条等)

return;
}
}

备忘录模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到先前保存的状态 如​​onSaveInstanceState​​​和​​onRestoreInstanceState​


  • 能够让状态回滚到某一时刻的状态
  • 实现了状态保存对象的封装,用户无需关心其实现细节
  • 要保存的对象如果成员变量过多的话,资源消耗也会相应增多。

外观模式

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。 如Glide.with().load().into(). Retrofit.create();等众多著名的开源框架的使用都是用了外观模式。Android中如Context中封装的 startActivity()方法,也是采用外观模式,将内部复杂的通过AMS跨进城启动activity的细节隐藏起来

优点


  • 降低了客户端与子系统类的耦合度,实现了子系统与客户之间的松耦合关系。
  • 外观类对子系统的接口封装,使得系统更易于使用。
  • 提高灵活性,不管子系统如何变化,只要不影响门面对象,就可以自由修改。

缺点


  • 增加新的子系统可能需要修改外观类的源代码,违背了“开闭原则”。
  • 所有子系统的功能都通过一个接口来提供,这个接口可能会变得很复杂。

单例模式

ActivityManagerSingleton

activityManager在系统中是一个单例,在启动源码中通过getService()方法获取具体的对象。

public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

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

protected abstract T create();

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

private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};

Android源码通过单例实现activityManager的获取,同时还封装了一个Singleton通用抽象类,借助新增的create()抽象方法,使其不知可以支持IActivityManager单例的获取,还可扩展到IWindowManager等其它单例的获取。将具体的对应类型的初始化下放给了具体业务,Singleton只是实现了一个单例的模版。

我们在设计架构解决差异性架构问题的时候,可以借鉴源码中的这种设计思想

如Choreographer的单例,则是借助ThreadLocal来实现。

public static Choreographer getInstance() {
return sThreadInstance.get();
}

private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};

通过阅读源码,发现最简单的单例模式,源码的呈现也是值得我们学习和探究的。

观察者模式

Android LiveData就是通过观察者模式提供的,LiveData使用示例,

class SecondActivity:AppCompatActivity() {
private lateinit var liveData: MutableLiveData<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
liveData= MutableLiveData<String>()
liveData.observe(this, Observer<String> { newContent ->
Log.i("tag5","newContent $newContent")
})
}
override fun onResume() {
super.onResume()
liveData.value="新数据"
}

}

将具体的observer封装到LifecycleBoundObserver中

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;

LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}

@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}

@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}

@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}

将Observer添加到一个统一的集合中,在数据发生变更的时候,利用迭代器,循环通知具体的observer

void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}