package com.cheng.zenofdesignpatterns.patterns.proxy;
import android.view.View;
import com.cheng.zenofdesignpatterns.ZoDPChapterBaseActivity;
import com.cheng.zenofdesignpatterns.patterns.proxy.common.Proxy;
import com.cheng.zenofdesignpatterns.patterns.proxy.common.RealSubject;
import com.cheng.zenofdesignpatterns.patterns.proxy.common.Subject;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamic.GamePlayerDynamicHandler;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamic.GamePlayerDynamic;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamic.IGamePlayerDynamic;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamiccommon.DynamicProxyDC;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamiccommon.MyInvocationHandler;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamiccommon.RealSubjectDC;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamiccommon.SubjectDC;
import com.cheng.zenofdesignpatterns.patterns.proxy.dynamiccommon.SubjectDynamicProxy;
import com.cheng.zenofdesignpatterns.patterns.proxy.force.GamePlayerForce;
import com.cheng.zenofdesignpatterns.patterns.proxy.force.GamePlayerProxyForce;
import com.cheng.zenofdesignpatterns.patterns.proxy.force.IGamePlayerForce;
import com.cheng.zenofdesignpatterns.patterns.proxy.normal.GamePlayerProxyNormal;
import com.cheng.zenofdesignpatterns.patterns.proxy.normal.IGamePlayerNormal;
import com.cheng.zenofdesignpatterns.patterns.proxy.section1.GamePlayer1;
import com.cheng.zenofdesignpatterns.patterns.proxy.section1.GamePlayerProxy1;
import com.cheng.zenofdesignpatterns.patterns.proxy.section1.IGamePlayer1;
import java.lang.reflect.InvocationHandler;
public class ZoDPProxyActivity extends ZoDPChapterBaseActivity {
@Override
protected void initData() {
mTitleTV.setText("代理模式");
String content = "定义:\n" +
"Provide a surrogate or placeholder for another object to control " +
"access to it.\n" +
"为其他对象提供一种代理以控制对这个对象的访问。\n\n" +
"代理模式的优点\n" +
"- 职责清晰\n" +
"真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理" +
"完成一件事务,附带的结果就是编程简洁清晰。\n" +
"- 高扩展性\n" +
"具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱" +
"如来佛的手掌(接口),那我们的代理类完全可以在不做任何修改的情况下使用。\n" +
"- 智能化\n" +
"可以看看Struts是如何把表单元素映射到对象上的。\n\n" +
"使用场景\n" +
"想想现实世界中,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要" +
"完成自己的答辩就成,其他的比如事前调查、事后追查都由律师来搞定,这就是为了减轻" +
"你的负担。代理模式的使用场景非常多,可以看看Spring AOP,这是是一个非常典型的" +
"动态代理。\n\n" +
"代理模式的扩展\n" +
"1. 普通代理\n" +
"就是需要知道代理的存在,然后才能访问。它的要求是客户端只能访问代理角色,而不能" +
"访问真实角色。\n" +
"注意 普通代理模式的约束问题,尽量通过团队内的编程规范来约束,因为每一个主题类" +
"是可被重用的和可维护的,使用技术约束的方式对系统维护是一种非常不利的因素。\n" +
"2. 强制代理\n" +
"一般的思维都是通过代理找到真实的角色,但是强制代理却是要‘强制’,你必须通过真实" +
"角色查找到代理角色,否则你不能访问。甭管你是通过代理类还是通过直接new一个主题" +
"角色类,都不能访问,只有通过真实角色指定的代理类才可以访问,也就是说由真实角色" +
"管理代理角色(明星和经纪人)。\n" +
"3. 动态代理\n" +
"动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说," +
"自己写代理类的方式就是静态代理。\n" +
"InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行代理。其中invoke" +
"方法是接口InvocationHandler定义必须实现的,它完成对真实方法的调用,即所有被" +
"代理的方法都由InvocationHandler接管实际的处理任务。\n\n" +
"最佳实践\n" +
"代理模式应用得非常广泛,大到一个系统框架、企业平台,小到代码片段、事务处理,稍不" +
"留意就用到代理模式。\n" +
"学习AOP时,弄清楚几个名词就成:切面(Aspect)、切入点(JoinPoint)、通知(Advice)、" +
"织入(Weave)就足够了。";
mContentTV.setText(content);
}
@Override
public void onClick(View v) {
// 1. Section1
// 定义一个痴迷的玩家
IGamePlayer1 player = new GamePlayer1("张三");
// 然后再定义一个代练者
IGamePlayer1 proxy = new GamePlayerProxy1(player);
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
proxy.login("zhangSan", "password");
// 开始杀怪
proxy.killBoss();
// 升级
proxy.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
// 2. 通用代理模式演示
Subject realSubject = new RealSubject();
Proxy proxy1 = new Proxy(realSubject);
proxy1.request();
// 3. 普通代理演示
// 定义一个代练者
IGamePlayerNormal proxy2 = new GamePlayerProxyNormal("张三");
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
proxy2.login("zhangsan", "password");
// 开始杀怪
proxy2.killBoss();
// 升级
proxy2.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
// 4. 强制代理演示
// 4.1 直接访问真实角色
// 定义个游戏的角色
IGamePlayerForce player41 = new GamePlayerForce("张三");
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
player41.login("zhangSan", "password"); // 请使用指定的代理访问
// 开始杀怪
player41.killBoss(); // 请使用指定的代理访问
// 升级
player41.upgrade(); // 请使用指定的代理访问
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
// 4.2 直接访问代理类
IGamePlayerForce player42 = new GamePlayerForce("张三");
// 定义一个代练者
IGamePlayerForce proxy42 = new GamePlayerProxyForce(player42);
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
proxy42.login("zhangSan", "password"); // 请使用指定的代理访问
// 开始杀怪
proxy42.killBoss(); // 请使用指定的代理访问
// 升级
proxy42.upgrade(); // 请使用指定的代理访问
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
// 4.3 强制代理演示
IGamePlayerForce player43 = new GamePlayerForce("张三");
// 获得指定的代理
IGamePlayerForce proxy43 = player43.getProxy();
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
proxy43.login("zhangSan", "password");
// 开始杀怪
proxy43.killBoss();
// 升级
proxy43.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
/**
* 强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。
* 高层模块只要调用getProxy就可以访问真实角色就可以访问真实角色的所有方法,
* 它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成
*/
// 5. 动态代理
// 定义一个痴迷的玩家
IGamePlayerDynamic player5 = new GamePlayerDynamic("张三");
// 然后定义一个代练者
InvocationHandler handler5 = new GamePlayerDynamicHandler(player5);
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2009-8-25 10:45");
//===============================================//
// 获得类的 ClassLoader
ClassLoader cl = player5.getClass().getClassLoader();
// 动态产生一个代理者
IGamePlayerDynamic proxy5 = (IGamePlayerDynamic) java.lang.reflect.Proxy.newProxyInstance(cl, new Class[] {IGamePlayerDynamic.class}, handler5);
// 登录
proxy5.login("zhangSan", "password");
// 开始杀怪
proxy5.killBoss();
// 升级
proxy5.upgrade();
//===============================================//
String str[] = {"zhangSan", "password"};
Class type[] = {String.class, String.class};
try {
handler5.invoke(null, player5.getClass().getMethod("login", type), str);
handler5.invoke(null, player5.getClass().getMethod("killBoss", String.class), null);
handler5.invoke(null, player5.getClass().getMethod("upgrade", String.class), null);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
// 记录结束游戏时间
System.out.println("结束时间是:2009-8-26 03:40");
// 6. 动态代理通用演示
// 6.1 普通动态代理调用
// 定义一个主题
SubjectDC subjectDC61 = new RealSubjectDC();
// 定义一个Handler
InvocationHandler handler61 = new MyInvocationHandler(subjectDC61);
// 定义主题的代理
SubjectDC proxy61 = DynamicProxyDC.newProxyInstance(subjectDC61.getClass().getClassLoader(),
subjectDC61.getClass().getInterfaces(), handler61);
// 代理的行为
proxy61.doSomething("Finish");
// 6.2 具体业务的动态代理调用
// 定义一个主题
SubjectDC subjectDC62 = new RealSubjectDC();
// 定义主题的代理
SubjectDC proxy62 = SubjectDynamicProxy.newProxyInstance(subjectDC62);
// 代理的行为
proxy62.doSomething("Finish");
/**
* 以上的动态代理是一个通用代理框架。如果想设计自己的AOP框架,完全可以在此基础上
* 扩展,这里设计的是一个通用代理,只要有一个接口,一个实现类,就可以使用该代理,
* 完成代理的所有功效。
*/
}
}