Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 淺談 java /Android設計模式--代理模式(Proxy pattern)

淺談 java /Android設計模式--代理模式(Proxy pattern)

編輯:關於Android編程

1,代理模式介紹

代理模式(Proxy Pattern)也稱為委托模式,其實代理模式在我們生活中非常常見,對於我們這些程序員來說最常接觸的莫過於代理上網了,連上代理服務器地址,我們就可以輕松在地在全球的網絡上進行遨游,還有比如小明來深圳比較早,買了好多房子,大家都知道現在深圳房子超級的貴,然後呢小明現在想回老家發展,於是就計劃將自己的房子賣掉,但是小明對這個又不很懂,而且平常也上班寫代碼,沒有時間,於是呢,他就找了搜房網來給他代理,將這房子賣出去,這也是一種代理.總而言之,也許你並不留意,但是代理模式確實是無處不在,現實生活中如此,我們code世界也是這樣,既然這樣,我們也來研究下代理模式到底有多麼的普遍,首先來看下定義.

2,代理模式的定義

為其他的對象提供一種代理以控制這個對象的訪問.

3,代理模式的使用場景

當無法或者不想直接訪問某個對象或者是訪問某個對象存在困難時,可以通過一個代理對象來間接地訪問,為了保證客戶端使用的透明性,委托對象與代理對象需要實現相同的接口,

4通用代碼

/**
 * 抽象主題類:
 * 該類的主要職責是申明真實主題與代理主題的共同接口,
 * 該類既可以是一個抽象類也可以是一個接口
 * @author Administrator
 *
 */
public abstract class Subject {
    //一個普通的業務方法
    public abstract void visit();
}
package com.proxy.simple;

/**
 * 真實主題類,
 * 該類也被稱為被代理類,或者是被委托類,該類定義了代理所表示的真實對象,
 * 由其執行的業務邏輯方法,而客戶類則通過代理類間接地調用真實主題類中定義的方法
 * @author Administrator
 *
 */
public class RealSubject extends Subject{
    @Override
    public void visit() {
        System.out.println("RealSubject");
    }
}
package com.proxy.simple;

/**
 * 代理類
 * 該類也被稱為委托類或者是代理類,該類持有一個真實的主題對象類的引用,
 * 在其所實現的接口方法中調用真實主題類中相應的接口方法執行,以此起到代理的作用.
 * @author Administrator
 *
 */
public class ProxySubject extends Subject{
    private RealSubject mRealSubject;
    public ProxySubject(RealSubject mRealSubject) {
        this.mRealSubject = mRealSubject;
    }

    @Override
    public void visit() {
        mRealSubject.visit();
    }
}
package com.proxy.simple;

/**
 * 客戶類,使用代理的類
 * @author Administrator
 *
 */
public class Client {
    public static void main(String args [] ){
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        proxySubject.visit();
    }
}   

以上就是一個通用的代碼模式的代碼模板

5角色介紹

抽象主題類:該類的主要職責是申明真實主題與代理主題的共同接口,該類既可以是一個抽象類也可以是一個接口 真實主題類:該類也被稱為被代理類,或者是被委托類,該類定義了代理所表示的真實對象,由其執行的業務邏輯方法,而客戶類則通過代理類間接地調用真實主題類中定義的方法 代理類:該類也被稱為委托類或者是代理類,該類持有一個真實的主題對象類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行,以此起到代理的作用. 客戶類,使用代理的類

6,代理模式的簡單實現

情景描述:小明來深圳比較早,買了好多房子,大家都知道現在深圳房子超級的貴,然後呢小明現在想回老家發展,於是就計劃將自己的房子賣掉,但是小明對這個又不很懂,而且平常也上班寫代碼,沒有時間,於是呢,他就找了搜房網來給他代理,將這房子賣出去. 主題類:
package com.proxy.static_;

public interface ISellHouse {
    /**
     * 看房
     */
    void lookHouse();
    /**
     * 介紹房子
     */
    void introduceHouse();
    /**
     * 預定房子
     */
    void bookHouse();
    /**
     * 交錢
     */
    void money();
    /**
     * 簽訂合同
     */
    void signContract();
    /**
     * 房子交付
     */
    void handOverHose();

}
真實主題類-被委托類:
package com.proxy.static_;

/**
 * 小明是一個真實的賣房者,他們家的房子要賣掉
 * @author Administrator
 *
 */
public class XiaoMingRealSellHouse implements ISellHouse{

    @Override
    public void lookHouse() {
        System.err.println("帶買房的人去看房子");
    }

    @Override
    public void introduceHouse() {
        System.err.println("給買房的人介紹房子");
    }

    @Override
    public void bookHouse() {
        System.err.println("買房子的人預定該房子");
    }

    @Override
    public void money() {
        System.err.println("買房子的要買下這個房子,然後付錢");
    }

    @Override
    public void signContract() {
        System.err.println("簽合同");
    }

    @Override
    public void handOverHose() {
        System.err.println("房子交付");
    }

}
代理類:
package com.proxy.static_;

/**
 * 搜房網 代理該房子的出售
 * @author Administrator
 *
 */
public class SouFang implements ISellHouse{
    private ISellHouse mSellHouse;

    public void setmSellHouse(ISellHouse mSellHouse) {
        this.mSellHouse = mSellHouse;
    }
    public SouFang(ISellHouse mSellHouse){
        this.mSellHouse = mSellHouse;
    }
    @Override
    public void lookHouse() {
        mSellHouse.lookHouse();
    }
    @Override
    public void introduceHouse() {
        mSellHouse.introduceHouse();
    }
    @Override
    public void bookHouse() {
        mSellHouse.bookHouse();
    }
    @Override
    public void money() {
        mSellHouse.money();
    }

    @Override
    public void signContract() {
        mSellHouse.signContract();
    }

    @Override
    public void handOverHose() {
        mSellHouse.handOverHose();
    }

}
客戶類:
package com.proxy.static_;

public class Client {
    public static void main(String args []) {
        ISellHouse sellHouse = new XiaoMingRealSellHouse();
        SouFang souFang = new SouFang(sellHouse);
        souFang.lookHouse();
        souFang.introduceHouse();;
        souFang.bookHouse();;
        souFang.money();;
        souFang.signContract();
        souFang.handOverHose();;
    }
}
運行結果
這裡寫圖片描述

7,簡單分析

大家可以看到,其實代理模式很簡單,主要還是一種委托的思想,真實對象將方法的執行委托給代理對象.而且委托的干淨利落而毫不做作,這是代理模式也稱為委托模式的原因,相信大家不難理解.其實我們的代理類可以代理很多個被代理的類,比如上面的例子,有一天小紅也要賣房子,那麼搜房網也同樣可以幫其代理.

8,動態代理

代理模式大概可以分成兩類,

靜態代理:
靜態代理如上述實例那樣,代理者的代碼由程序員自己或通過一些自動化的工具生成固定的代碼再對其進行編譯,也就是說在我們的代碼運行前代理類的class的編譯文件就已經存在. 動態代理:
通過反射機制動態地生成代理者的對象,也就是說我們在code階段壓根就不知道代理者是誰,代理誰我們將會在執行階段決定.而java也給我們提供了一個便捷的動態代理的接口InvocationHandler,實現該接口需要重寫其調用方法invoke

動態代理代碼如下:

package com.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 構建動態代理類
 * @author Administrator

 */
public class DynamicProxy implements InvocationHandler{
    private Object object;
    public DynamicProxy(Object object) {
        this.object = object;

    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        return result;
    }

}

客戶類代碼如下:

package com.proxy.dynamic;
import java.lang.reflect.Proxy;
import com.proxy.static_.ISellHouse;
import com.proxy.static_.XiaoMingRealSellHouse;
public class Main {
    public static void main(String args [] ){
        //被委托的對象
        ISellHouse xiaoming = new XiaoMingRealSellHouse();
        DynamicProxy proxy = new DynamicProxy(xiaoming);
        ClassLoader loader = xiaoming.getClass().getClassLoader();
        ISellHouse souFang = 
                (ISellHouse) Proxy.newProxyInstance(loader, new Class[]{ISellHouse.class},proxy );
        souFang.lookHouse();
        souFang.introduceHouse();
        souFang.bookHouse();
        souFang.money();
        souFang.signContract();
        souFang.handOverHose();
    }
}

9,Android端代理模式簡單實例:

以Android端發送通知為例,不同的手機版本發送不同樣的通知;

抽象主題類:
package com.example.administrator.proxy;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.NotificationCompat;

/**
 * Created by Administrator on 2016/9/28.
 */
public abstract class Notify {
    protected Context mContext;
    protected NotificationManager mNotificationManager;
    protected NotificationCompat.Builder mBuilder;
    public Notify(Context context){
        this.mContext = context;
        init();

    }
    protected  void init(){
        mBuilder = new NotificationCompat.Builder(mContext);
        mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder.setSmallIcon(R.mipmap.ic_launcher).
                setContentIntent(PendingIntent.getActivity(mContext,0,
                        new Intent(mContext,MainActivity.class),
                        PendingIntent.FLAG_UPDATE_CURRENT));
    }

    public abstract void send();
    public abstract void cannel();
}
被委托類
package com.example.administrator.proxy;

import android.app.Notification;
import android.content.Context;
import android.widget.RemoteViews;

/**
 * Created by Administrator on 2016/9/28.
 */
public class NotifyNormal extends Notify {
    public NotifyNormal(Context context) {
        super(context);
    }

    @Override
    public void send() {
        Notification n = mBuilder.build();
        n.contentView = new RemoteViews(mContext.getPackageName(),R.layout.layout_notify);
        mNotificationManager.notify(0,n);
    }

    @Override
    public void cannel() {
        mNotificationManager.cancel(0);
    }
}
package com.example.administrator.proxy;

import android.app.Notification;
import android.content.Context;
import android.widget.RemoteViews;

/**
 * Created by Administrator on 2016/9/28.
 */
public class NotifyBig extends Notify {
    public NotifyBig(Context context) {
        super(context);
    }

    @Override
    public void send() {
        Notification n = mBuilder.build();
        n.contentView = new RemoteViews(mContext.getPackageName(),R.layout.layout_notify_big);
        mNotificationManager.notify(0,n);
    }

    @Override
    public void cannel() {
        mNotificationManager.cancel(0);
    }
}
代理類
package com.example.administrator.proxy;

import android.content.Context;
import android.os.Build;

/**
 * Created by Administrator on 2016/9/28.
 */
public class NotifyProxy extends Notify {
    private Notify mNotify;
    public NotifyProxy(Context context) {
        super(context);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            mNotify = new NotifyNormal(context);
        }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            mNotify = new NotifyBig(context);
        }
    }
    @Override
    public void send() {
        mNotify.send();
    }
    @Override
    public void cannel() {
        mNotify.cannel();
    }
}

layout_notify.xml




    

layout_notify_big.xml




    

客戶端類:
package com.example.administrator.proxy;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button mButtonSend;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    private void init() {
        mButtonSend = (Button) findViewById(R.id.btn_send);
        mButtonSend.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_send:
                send();
                break;
        }
    }

    private void send(){
        new NotifyProxy(this).send();
    }


}

activity_main.xml


10,總結

代理模式基本上沒有什麼缺點,它是細分化很小的一種設計模式,要真要說一個缺點,那就是對類的增加,

至此,整個代理模式就講完了,是不是很簡單呢.

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved