Android 設計模式之代理模式

在平常開發過程當中時常須要用到設計模式,可是設計模式有23種,如何將這些設計模式瞭然於胸而且能在實際開發過程當中應用得駕輕就熟呢?和我一塊兒跟着《Android源碼設計模式解析與實戰》一書邊學邊應用吧!

設計模式系列文章

今天咱們要講的是代理模式(委託模式)


定義

爲其餘對象提供一種代理以控制對這個對象的訪問設計模式

使用場景

  • 當沒法或不想直接訪問某個對象或訪問某個對象存在困難時,能夠經過一個代理對象來間接訪問,爲了保證客戶端使用的透明性,委託對象與代理對象須要實現相同的接口

使用例子

  • Android源碼中的ActivityManagerProxy代理ActivityManagerService類

實現

三大角色

  • 抽象主題類:聲明真實主題與代理的共同接口方法,該類既能夠是一個抽象類也能夠是一個接口
  • 真實主題類:也稱爲被委託類或被代理類,該類定義了代理所表示的真實對象,由其執行具體的業務邏輯
  • 代理類:也稱爲委託類或代理類,該類持有一個對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行

實現的要點

  • 代理模式從實現上分爲靜態代理和動態代理,這裏咱們主要關注靜態代理
  • 代理類和被代理類都要繼承或實現相同的接口或方法
  • 代理類經過被代理類的引用來調用具體的業務邏輯

實現方式

這裏咱們主要經過適配不一樣API版本下發送消息Notification來應用代理模式

抽象主題類

public abstract class Notify {
    protected Context context;
    protected NotificationManager notificationManager;
    protected NotificationCompat.Builder builder;

    public Notify(Context context) {
        this.context = context;
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        builder = new NotificationCompat.Builder(context);
        builder.setSmallIcon(R.drawable.ic_launcher)
                .setContentIntent(PendingIntent.getActivity(context, 0,
                        new Intent(context, NotifyActivity.class),
                        PendingIntent.FLAG_UPDATE_CURRENT));
    }

    /**
     * 發送一條通知
     */
    public abstract void send();

    /**
     * 取消一條通知
     */
    public abstract void cancel();
}
複製代碼
  • 初始化了子類都會用到的NotificationManager和Builder,猜猜NotificationCompat類裏面用了什麼設計模式?
  • 定義了2個公共的方法:send方法和cancel方法

真實主題類(被代理類)

  • 常規的通知的構建
public class NotifyNormal extends Notify {

    public NotifyNormal(Context context) {
        super(context);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        Notification notification = builder.build();
        notificationManager.notify(0, notification);
    }

    @Override
    public void cancel() {
        notificationManager.cancel(0);
    }
}
複製代碼
  • 大視圖的通知的構建
public class NotifyBig extends Notify {

    public NotifyBig (Context context) {
        super(context);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomBigContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        Notification notification = builder.build();
        notificationManager.notify(0, notification);
    }

    @Override
    public void cancel() {
        notificationManager.cancel(0);
    }
}
複製代碼
  • 浮動展現的通知的構建
public class NotifyHeadersUp extends Notify {

    public NotifyHeadersUp (Context context) {
        super(context);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomBigContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomHeadsUpContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        Notification notification = builder.build();
        notificationManager.notify(0, notification);
    }

    @Override
    public void cancel() {
        notificationManager.cancel(0);
    }
}
複製代碼

代理類

public class NotifyProxy extends Notify {

    private Notify notify;

    public NotifyProxy (Context context) {
        super(context);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            notify = new NotifyHeadersUp(context);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            notify = new NotifyBig(context);
        } else {
            notify = new NotifyNormal(context);
        }
    }

    @Override
    public void send() {
        notify.send();
    }

    @Override
    public void cancel() {
        notify.cancel();
    }
}
複製代碼

調用

new NotifyProxy(MainActivity.this).send();
複製代碼
  • 可見接口很簡潔,經過代理模式,咱們把複雜的判斷和生成通知的邏輯都屏蔽了,這樣代碼更加清晰

補充

  • 不知道你們看了上面的示例代碼有什麼想法?有沒有能夠優化的地方呢?
  • 上面的示例中,3個Notify的子類中有不少重複的代碼,有沒有什麼方法能進一步優化呢?

總結

  • 代理模式應用普遍,會常常和其餘設計模式結合使用
  • 代理模式是細分化至很小的一種設計模式,幾乎沒有缺點

歡迎關注個人微信公衆號,期待與你一塊兒學習,一塊兒交流,一塊兒成長! bash

AntDream
相關文章
相關標籤/搜索