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,总结
代理模式基本上没有什么缺点,它是细分化很小的一种设计模式,要真要说一个缺点,那就是对类的增加,
至此,整个代理模式就讲完了,是不是很简单呢.