设计模式-外观模式
retrofit。引入一个外观角色,来简化客户端与系统之间的交互。加快功能速度,降低系统的复杂度
- 外观设计模式详解
- 外观模式在android的实际运用
11_1-11-7[01_29_39][20180801-220956-1].jpg
1.外观设计模式详解
1.概念
外观模式的主要目的在于让外部减少与子系统内部多个模块之间的交互,从而让外部能够更简单的使用子系统。它负责把客户端的请求转发给子系统内部的各个模块进行处理
2.使用场景
1.当你要为一个复杂子系统提供一个简单接口时。
2.客户程序与抽象类的实现部分之间存在很大的依赖性。
3.当你需要构建一个层次结构的子系统时。
3.UML结构图分析
图:
Facade ModuleA
---------------- ---> ----------------
+testOperation();
client ModuleB
------------ ---> ----------------
+test();
ModuleC
---> ----------------
+test();
使用了Facade这个外观类之后,客户端就不需要关注 子系统各模块的变化了。
4.实际代码分析
pubic class ModuleA{
public void testFuncA(){
System.out.println("This is Function From ModuleA")
}
}
public class Facade{
private ModuleA moduleA;
private ModuleA moduleB;
private ModuleA moduleC;
private static Facade mFacade;
private Facade(){
moduleA = new ModuleA();
moduleB = new ModuleB();
moduleC = new ModuleC();
}
public static Facade getInstance(){
if(mFacade == null){
mFacade = new Facade();
}
return mFacade;
}
public void testOperation(){
moduleA.testFuncA();
moduleB.testFuncB();
moduleC.testFuncC();
}
}
Facade 持有了三个模块对象,并将其初始化
单例模式实现,整个系统只有一个
调用: Facade.getInstance().testOperation();
5.外观模式优点
1.由于Facade类封装了各个模块交互的过程,如果后续内部模块调用关系发生了变化,只需要修改Facade实现就可以了。
2.Facade实现可以被多个客户调用的(单例)
2.外观模式在android的实际运用(ContextImpl)
图:
1.android开启一个进程的时候,它首先会调用 ActivityThead的static void Main(String[] argsw )方法:
1.trace路径 2.初始环境变量 3.打印些报告 4.初始化文件
5.比较重要的 Looper.prepareMainLooper();
6.创建一个ActivityThread thread = new ActivityThread();//
既然有looper,那么就会发送消息。如何发送的消息,调用了什么方法来进行开启Activity
handleMessage(Message msg){}方法中
switch(msg.what){
case LAUNCH_ACTIVITY:
final ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo,r.compatInfo)
handleLaunchActivity(r,null,"LAUNCH_ACTIVITY")
}
handleLaunchActivity(ActivityClientRecord r,Intent customIntent,String reason)
主要是调用了 Activity a = performLaunchActivity(r,customIntent)来进行具体操作
performLaunchActivity(ActivityClientRecord r,Intent customIntent)
初始化了很多,ActivityInfo,ComponentName,Activity
最重要的用了一个activity.attach(appContext,this,getInstrumentation(),r.token
r.ident,app,r.intent,r.activityInfo,title,r.parent,r.embeddedID,r.lastNonConfigrurationInstance,config,r.referrer,r.voiceInteractor,window)方法
这个方法将将appContex,infomation,和app号等关联在一起
activity的父类是Context,所以activity拥有context的方法:比如开启Activity,发送广播,bindService等等
activity内部并不实现这些具体的功能,它只是继承Conext接口,他的具体操作会交给ContexImpl这个对象来做,这里使用的是ContextImpl的外观模式
activity的attach方法做了很多繁琐功能,第一行attachBaseContext(context);
将我们的一个context参数传递给父类ContextThemeWraper的父类ContextImpl 的属性mBase字段
ContextWrapper类
字段 Context mBase;
这里activity充当是的代理类的角色,通过Activity对象findViewById,setOnClickxx都是代理了ContextImpl的操作,它内部调用的都是ContextImpl额方法
ContextImpl类
方法:startActivity(Intent intent){
warnIfCallingFromSystemProcess();
startActivity(intent,null);
}
startActivity(intent,Bundle options){
warnIfCallingFromSystemProcess();
mMainThread.getInstrumentation().exxxxActivity(getOuterContext(),mMainThread.getApplicationThread(),null,(Activity)null,intent,-1,options);
}
主线程的instrumentation来开启我们的activity,传入全局的activity,全局的线程
如果每次开启activity都要做如此繁杂的操作时,会太复杂了,所以ContextImpl把四大组件的startActivty,bindService都封装好了,只要通过这个抽象的统一接口就是可以操作startActivity,这样就降低了用户和系统交互的成本,屏蔽了一些细节。
通过一个高层的接口统一提供给用户,用户不会知道整个子系统模块的变化,调用外观类即可
11_1-11-7[01_29_39][20180801-220956-1].jpg
11_1-11-7[01_34_49][20180801-222602-2].jpg
11_1-11-7[01_36_15][20180802-082845-4].jpg
11_1-11-7[01_36_32][20180802-082838-3].jpg
11_1-11-7[01_36_37][20180802-083026-5].jpg
11_1-11-7[01_36_48][20180802-083049-6].jpg
11_1-11-7[01_36_52][20180802-083147-7].jpg
11_1-11-7[01_37_32][20180802-083602-0].jpg
11_1-11-7[01_37_36][20180802-083555-9].jpg
11_1-11-7[01_37_37][20180802-083550-8].jpg
11_1-11-7[01_37_50][20180802-084153-2].jpg
11_1-11-7[01_37_50][20180802-084154-3].jpg
11_1-11-7[01_39_01][20180802-084133-1].jpg