浅谈 java /Android设计模式--代理模式(Proxy pattern)

转载地址:http://www.2cto.com/kf/201609/551741.html



1,代理模式介绍

代理模式(Proxy Pattern)也称为委托模式,其实代理模式在我们生活中非常常见,对于我们这些程序员来说最常接触的莫过于代理上网了,连上代理服务器地址,我们就可以轻松在地在全球的网络上进行遨游,还有比如小明来深圳比较早,买了好多房子,大家都知道现在深圳房子超级的贵,然后呢小明现在想回老家发展,于是就计划将自己的房子卖掉,但是小明对这个又不很懂,而且平常也上班写代码,没有时间,于是呢,他就找了搜房网来给他代理,将这房子卖出去,这也是一种代理.总而言之,也许你并不留意,但是代理模式确实是无处不在,现实生活中如此,我们code世界也是这样,既然这样,我们也来研究下代理模式到底有多么的普遍,首先来看下定义.

2,代理模式的定义

为其他的对象提供一种代理以控制这个对象的访问.

3,代理模式的使用场景

当无法或者不想直接访问某个对象或者是访问某个对象存在困难时,可以通过一个代理对象来间接地访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口,

4通用代码

?
1
2
3
4
5
6
7
8
9
10
11
/**
  * 抽象主题类:
  * 该类的主要职责是申明真实主题与代理主题的共同接口,
  * 该类既可以是一个抽象类也可以是一个接口
  * @author Administrator
  *
  */
public abstract class Subject {
     //一个普通的业务方法
     public abstract void visit();
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.proxy.simple;
 
/**
  * 真实主题类,
  * 该类也被称为被代理类,或者是被委托类,该类定义了代理所表示的真实对象,
  * 由其执行的业务逻辑方法,而客户类则通过代理类间接地调用真实主题类中定义的方法
  * @author Administrator
  *
  */
public class RealSubject extends Subject{
     @Override
     public void visit() {
         System.out.println( "RealSubject" );
     }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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();
     }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,代理模式的简单实现

情景描述:小明来深圳比较早,买了好多房子,大家都知道现在深圳房子超级的贵,然后呢小明现在想回老家发展,于是就计划将自己的房子卖掉,但是小明对这个又不很懂,而且平常也上班写代码,没有时间,于是呢,他就找了搜房网来给他代理,将这房子卖出去. 主题类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.proxy.static_;
 
public interface ISellHouse {
     /**
      * 看房
      */
     void lookHouse();
     /**
      * 介绍房子
      */
     void introduceHouse();
     /**
      * 预定房子
      */
     void bookHouse();
     /**
      * 交钱
      */
     void money();
     /**
      * 签订合同
      */
     void signContract();
     /**
      * 房子交付
      */
     void handOverHose();
 
}
真实主题类-被委托类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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( "房子交付" );
     }
 
}
代理类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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();
     }
 
}
客户类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

动态代理代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
     }
 
}

客户类代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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端发送通知为例,不同的手机版本发送不同样的通知;

抽象主题类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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();
}
被委托类
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 );
     }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 );
     }
}
代理类
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

?
1
2
3
4
5
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<linearlayout android:gravity= "center" android:layout_height= "match_parent" android:layout_width= "match_parent" xmlns:android= "http://schemas.android.com/apk/res/android" >
 
     <textview android:layout_height= "match_parent" android:layout_width= "match_parent" android:text= "notify_normal" android:textsize= "16sp" >
</textview></linearlayout>

layout_notify_big.xml

?
1
2
3
4
5
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<linearlayout android:gravity= "center" android:layout_height= "match_parent" android:layout_width= "match_parent" xmlns:android= "http://schemas.android.com/apk/res/android" >
 
     <textview android:layout_height= "match_parent" android:layout_width= "match_parent" android:text= "notify_big" android:textsize= "16sp" >
</textview></linearlayout>
客户端类:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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

?
1
2
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<relativelayout android:layout_height= "match_parent" android:layout_width= "match_parent" android:paddingbottom= "@dimen/activity_vertical_margin" android:paddingleft= "@dimen/activity_horizontal_margin" android:paddingright= "@dimen/activity_horizontal_margin" android:paddingtop= "@dimen/activity_vertical_margin" tools:context= "com.example.administrator.proxy.MainActivity" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" ><button android:id= "@+id/btn_send" android:layout_height= "wrap_content" android:layout_width= "match_parent" android:text= "发送" ></button></relativelayout>

10,总结

代理模式基本上没有什么缺点,它是细分化很小的一种设计模式,要真要说一个缺点,那就是对类的增加,

至此,整个代理模式就讲完了,是不是很简单呢.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值