代理模式
什么是代理模式?
代理模式就是我懒,有工作我不想做,我找别人帮我做。但是我怎么知道他能帮我做呢?所以我们要彼此了解对方,我们要实现共同的接口。
上类图

随着科技的发达,机器人越来越先进,终于有一天,机器人做的跟我们一摸一样,然后他们负责替我们做工作,我们吃喝玩乐,来我们就用代码创建两个机器人。
以下是代码:
首先是定义共同的接口,我们能做的事情,机器人也能要能做。
/**
 * Created by 29028 on 2017/6/19.
 *
 * 自己的接口
 */
public interface ISlef {
    //我能干什么
    //吃
    public void eat();
    //工作
    public void doWork();
}
接着定义两个机器人替身。
替身1号
/**
 * Created by 29028 on 2017/6/19.
 * 机器人替身1号 我会的他也会
 */
public class ProxyRobot1 implements ISlef {
    public void eat() {
        Log.d("AAA","机器人替身1号吃电");
    }
    public void doWork() {
        Log.d("AAA","机器人替身1号帮我做工作");
    }
}
替身1号
/**
 * Created by 29028 on 2017/6/19.
 * 机器人替身2号 我会的他也会
 */
public class ProxyRobot2 implements ISlef {
    public void eat() {
        Log.d("AAA","机器人替身2号吃电");
    }
    public void doWork() {
        Log.d("AAA","机器人替身2号帮我做工作");
    }
}
再接着创建我们自己
/**
 * Created by 29028 on 2017/6/19.
 * 真的自己
 */
public class TrueSelf implements ISlef {
    private ISlef slef;
    //默认让一号来
    public TrueSelf(){
        slef =new ProxyRobot1();
    }
    //设置替身 我想谁几号替我就让几号来
    public void setProxy(ISlef slef){
        this.slef = slef;
    }
    //吃东西这事还是我们自己来比较好
    public void eat() {
        Log.d("AAA","我悠哉悠哉的吃肉");
    }
    public void doWork() {
        slef.doWork();
    }
}
终于弄好了两个替身,下面我们看看替身的威力吧
老板去让我做事,我照着做了,老板其实不知道是谁在做。
 private void doThings() {
        TrueSelf self=new TrueSelf();
        self.doWork();
        self.eat();
    }
打印结果
机器人替身1号帮我做工作
我悠哉悠哉的吃肉
老让1号替身怕他太累了
 private void doThings() {
        TrueSelf self=new TrueSelf();
        self.setProxy(new ProxyRobot2());
        self.doWork();
        self.eat();
    }
打印结果
机器人替身2号帮我做工作
我悠哉悠哉的吃肉
是不是美滋滋,我们总结一下,代理模式主要是使用了Java的多态,干活的是被代理类,而作为代理的我们只负责悠哉悠哉的吃肉就行了。
下面是再Android开发中的实践
我们以上篇app中的沉浸式为例,使用代理模式重构一下我们的代码。
首先定义一个公共的抽象类
abstract class Immersion {
    protected final Activity activity;
    protected final boolean isShowUi;
    public Immersion(Activity activity, boolean isShowUi){
        this.activity = activity;
        this.isShowUi = isShowUi;
        if(isShowUi) {
            toggleHideyBar(activity);
        }
    }
    public abstract void setStatusColor(View titleBar, @ColorRes int resId);
    public abstract  void setStatusPicture(View titleBar, @DrawableRes int drawableId);
    public abstract void setStatusAndNaviagtion(View titleBar, View botoomBar,  @ColorRes int resId );
    /**
     * dip 转 px
     */
    protected static int dp2px(int dp,Activity activity) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,activity.getResources().getDisplayMetrics());
    }
    /**
     * 开关
     */
    protected static void toggleHideyBar(Activity activity) {
        int newUiOptions = activity.getWindow().getDecorView().getSystemUiVisibility();
        if (Build.VERSION.SDK_INT >= 14) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        }
        if (Build.VERSION.SDK_INT >= 16) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN;
        }
        if (Build.VERSION.SDK_INT >= 18) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        }
        activity.getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
    }
    /**
     * 获取状态栏的高度
     */
    protected static int getStatusHeight(Activity activity){
        int stastusHeight=-1;
        int statusId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if(statusId>0){
            stastusHeight = activity.getResources().getDimensionPixelSize(statusId);
        }
        return stastusHeight==-1?dp2px(24,activity):stastusHeight;
    }
    /**
     * 获取底部导航栏的高度
     */
    protected static int getNavigationHeight(Activity activity){
        int navigationHeight=-1;
        int navigationId = activity.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if(navigationId>0){
            navigationHeight=activity.getResources().getDimensionPixelSize(navigationId);
        }
        return navigationHeight==-1?dp2px(48,activity):navigationHeight;
    }
}
在定义一个适配4.4的被代理类。
class ImmersionApi19 extends Immersion {
    public ImmersionApi19(Activity activity, boolean isShowUi) {
        super(activity, isShowUi);
    }
    public void setStatusColor(View titleBar, @ColorRes int resId) {
       int color;
       if(resId > 0) {
          color = activity.getResources().getColor(resId);
       } else {
          color = Color.parseColor("#FF4081");
       }
       int statusHeight = getStatusHeight(activity);
       if(titleBar!=null){
            ViewGroup.LayoutParams params = titleBar.getLayoutParams();
            params.height+=statusHeight;
            titleBar.setLayoutParams(params);
            titleBar.setPadding(titleBar.getPaddingLeft(),
                    titleBar.getPaddingTop()+statusHeight,
                    titleBar.getPaddingRight(),
                    titleBar.getPaddingBottom());
            titleBar.setBackgroundColor(color);
         }
    }
    public void setStatusPicture(View titleBar, @DrawableRes int drawableId) {
        Drawable drawableBg;
        if(drawableId > 0) {
            drawableBg = activity.getResources().getDrawable(drawableId);
        } else {
            drawableBg = activity.getResources().getDrawable(livesun.translucent.R.drawable.ic_launcher);
        }
        int statusHeight = getStatusHeight(activity);
            if(titleBar != null) {
                ViewGroup.LayoutParams decorView1 = titleBar.getLayoutParams();
                decorView1.height += statusHeight;
                titleBar.setLayoutParams(decorView1);
                titleBar.setPadding(titleBar.getPaddingLeft(),
                        titleBar.getPaddingTop() + statusHeight,
                        titleBar.getPaddingRight(),
                        titleBar.getPaddingBottom());
                titleBar.setBackground(drawableBg);
            }
    }
    public void setStatusAndNaviagtion(View titleBar, View botoomBar, @ColorRes int resId) {
        //时间原因 暂不实现
    }
以及一个适配5.0的被代理类。
class ImmersionApi21 extends Immersion {
    public ImmersionApi21(Activity activity, boolean isShowUi) {
        super(activity, isShowUi);
    }
    public void setStatusColor(View titleBar, @ColorRes int resId) {
       int color;
       if(resId > 0) {
          color = activity.getResources().getColor(resId);
       } else {
          color = Color.parseColor("#FF4081");
       }
       activity.getWindow().setStatusBarColor(color);
       titleBar.setBackgroundColor(color);
    }
    public void setStatusPicture(View titleBar, @DrawableRes int drawableId) {
//      new ImmersionApi19(activity,isShowUi).setStatusPicture(titleBar, drawableId);
        View decorView = activity.getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(option);
        titleBar.setBackground(activity.getResources().getDrawable(drawableId));
    }
    public void setStatusAndNaviagtion(View titleBar, View botoomBar, @ColorRes int resId) {
        //暂时不实现
    }
}
接下来就是我们的代理类
public class ImmersionProxy extends Immersion {
    private  Immersion immersion;
    public ImmersionProxy(Activity activity, boolean isShowUi) {
        super(activity, isShowUi);
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT
                &&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP
                ){
            immersion = new ImmersionApi19(activity,isShowUi);
        }
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            immersion=new ImmersionApi21(activity,isShowUi);
        }
    }
    public void setStatusColor(View titleBar, @ColorRes int resId) {
        immersion.setStatusColor(titleBar,resId);
    }
    public void setStatusPicture(View titleBar, @DrawableRes int drawableId) {
        immersion.setStatusPicture(titleBar,drawableId);
    }
    public void setStatusAndNaviagtion(View titleBar, View botoomBar, @ColorRes int resId) {
        immersion.setStatusAndNaviagtion(titleBar,botoomBar,resId);
    }
}
然后,我们就可以很开心的调用了,我们不必关心是调用API19还是API21,只管在Activity中的OnCreat方法调用
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_main);
        Toolbar toolbar= (Toolbar) findViewById(R.id.toolbar);
        ImmersionProxy proxy = new ImmersionProxy(this, false);
        proxy.setStatusColor(toolbar,R.color.colorAccent);
    }

