UML关系简单介绍
UML简单使用的介绍
创建型设计模式
Android设计模式-单例模式
Android设计模式-工厂模式
Android设计模式-抽象工厂模式
Android设计模式-建造者模式
Android设计模式-原型模式
结构型设计模式
Android设计模式-代理模式
Android设计模式-装饰模式
Android设计模式-适配器模式
Android设计模式-组合模式
Android设计模式-门面模式
Android设计模式-桥接模式
Android设计模式-享元模式
行为型设计模式
Android设计模式-策略模式
Android设计模式-命令模式
Android设计模式-责任链模式
Android设计模式-模版方法模式
Android设计模式-迭代器模式
Android设计模式-观察者模式
Android设计模式-备忘录模式
Android设计模式-中介者模式
Android设计模式-访问者模式
Android设计模式-状态模式
Android设计模式-解释器模式
1.定义
为其他对象提供一种代理以控制对这个对象的访问
2.代理模式通用类图
角色介绍
- Subject 抽象主题,可以是抽象类也可以是接口,realsubject和proxy都是继承或者实现自它。
- RealSubject 真实主题类,也就是被代理者,也就是具体任务逻辑的执行者
- Proxy 代理类,也叫委托类,一般持有真实主题类的引用,在相应的方法中,调用真实主题类的对应方法。
3.简单实现
3.1抽象主题类
public interface Subject {
void doSomething();
}
3.2 真实主题类
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("买肉!");
}
}
3.3 代理类
public class ProxySubject implements Subject {
Subject subject=null;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void doSomething() {
doBefore();
System.out.println("我代理者,我要!!");
this.subject.doSomething();
doAfter();
}
private void doBefore(){
System.out.println("我是代理者前置动作");
}
private void doAfter(){
System.out.println("我是代理者后置动作");
}
}
3.4场景调用
public class MyClass {
public static void main(String args[]) {
Subject realSubject=new RealSubject();
Subject proxySubject=new ProxySubject(realSubject);
proxySubject.doSomething();
}
}
打印结果为
我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作
3.5例子简介
被代理类realSubject与代理类proxySubject都实现了接口Subject,比如你想去买肉吃了,realSubject就是你,但是你不想动弹,就让你都舍友帮你去买肉回来,proxySubject就相当于你的舍友。你舍友肯定是要知道他是帮谁买肉的,否则回来谁给钱呀。。这个目标就是通过构造函数传过来的subject,也就是在场景类中传过来的realSubject。另外代理模式,也常可在代理的方法执行前后,插入一些自己的逻辑,比如上例中的doBefore和doAfter。
4.扩展
4.1普通代理和强制代理
普通代理就是我们要知道代理的存在,也就是代理类后才能访问。而强制代理则是调用者直接调用真实角色而不用关心代理是否存在,其代理的产生是由真实角色决定的
4.1.1普通代理
修改上面的例子,将其改为普通代理模式
4.1.1.1 抽象主题类
public interface Subject {
void doSomething();
}
4.1.1.2 真实主题类
public class RealSubject implements Subject {
public RealSubject(Subject subject) throws Exception{
if (subject==null){
throw new Exception();
}
}
@Override
public void doSomething() {
System.out.println("买肉!");
}
}
4.1.1.3 代理类
public class ProxySubject implements Subject {
private Subject subject=null;
public ProxySubject() {
try {
subject=new RealSubject(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void doSomething() {
doBefore();
System.out.println("我代理者,我要!!");
this.subject.doSomething();
doAfter();
}
private void doBefore(){
System.out.println("我是代理者前置动作");
}
private void doAfter(){
System.out.println("我是代理者后置动作");
}
}
4.1.1.4 场景调用
public class MyClass {
public static void main(String args[]) {
Subject proxySubject=new ProxySubject();
proxySubject.doSomething();
}
}
打印结果为
我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作
4.1.1.5 例子总结
从打印结果中,可以看出,在该模式下,没有发生变化,但是在调用的时候,只需要调用代理类就可以进行相应的任务,不用知道具体的真实主题类是谁。屏蔽了真实角色的变更对高层模块的影响,真实主题类想怎么修改就怎么修改,对高层次模块没有任何影响,只要你实现了对应的方法,对扩展性较高对场合特别适合。
4.1.2 强制代理
强制代理简单理解为就是必须通过真实主题类获得的代理,才能进行相应的操作。就相当于高层模块new了一个真实主题类,但是返回的确实一个代理角色。
将上面的例子修改为强制代理
4.1.2.1 抽象主题类
public interface Subject {
void doSomething();
}
4.1.2.2 真实主题类
public class RealSubject implements Subject {
private Subject proxySubject=null;
public RealSubject() {
}
public Subject getProxySubject(){
this.proxySubject=new ProxySubject(this);
return this.proxySubject;
}
@Override
public void doSomething() {
if (proxySubject!=null) {
System.out.println("买肉!");
}else {
System.out.println("请使用指定的代理进行访问");
}
}
}
4.1.2.3 代理类
public class ProxySubject implements Subject {
private Subject subject=null;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void doSomething() {
doBefore();
System.out.println("我代理者,我要!!");
this.subject.doSomething();
doAfter();
}
private void doBefore(){
System.out.println("我是代理者前置动作");
}
private void doAfter(){
System.out.println("我是代理者后置动作");
}
}
4.1.2.4 场景调用
public class MyClass {
public static void main(String args[]) {
Subject real=new RealSubject();
real.doSomething();
}
}
打印结果为
请使用指定的代理进行访问
public class MyClass {
public static void main(String args[]) {
Subject real=new RealSubject();
Subject proxy=new ProxySubject(real);
proxy.doSomething();
}
}
打印结果为
我是代理者前置动作
我代理者,我要!!
请使用指定的代理进行访问
我是代理者后置动作
public class MyClass {
public static void main(String args[]) {
Subject real=new RealSubject();
Subject proxy=((RealSubject) real).getProxySubject();
proxy.doSomething();
}
}
打印结果为
我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作
4.1.2.5例子总结
以上的例子即为强制代理,调用的时候,只能通过真实角色指定的代理角色,才能访问具体的功能逻辑,不允许直接访问真实角色。高层模块只要调用getProxySubject就可以获取访问真实角色的指定代理类,不需要重新产生一个新的代理类。
4.2动态代理
动态代理在实现阶段不管关心代理谁,而在运行阶段才指定代理那一个对象。现在很流行的一个aop编程,核心就是使用了动态代理技术。
动态代理主要用到了InvocationHandler类
4.2.1动态代理简单实现
动态代理类
public class DynamicProxy implements InvocationHandler {
//被代理的对象
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("我是动态代理!");
Object result=method.invoke(object,objects);
return result;
}
}
真实主题类
修改回最初的样子。。。
public class RealSubject implements Subject {
private Subject proxySubject=null;
public RealSubject() {
}
// public Subject getProxySubject(){
// this.proxySubject=new ProxySubject(this);
// return this.proxySubject;
// }
@Override
public void doSomething() {
// if (proxySubject!=null) {
System.out.println("买肉!");
// }else {
// System.out.println("请使用指定的代理进行访问");
// }
}
}
场景类调用
public class MyClass {
public static void main(String args[]) {
Subject real=new RealSubject();
DynamicProxy dynamic=new DynamicProxy(real);
ClassLoader classLoader=real.getClass().getClassLoader();
Subject dynamicSubject= (Subject) Proxy.newProxyInstance(classLoader,new Class[]{Subject.class},dynamic);
dynamicSubject.doSomething();
}
}
打印结果为
,
我是动态代理!
买肉!
动态代理总结
动态代理是在程序运行期间根据反射等机制动态的生成。代理类和委托类的关系是在程序运行期确定的。
另外动态代理如果想要在相应位置添加前后操作,则可以在动态代理类中添加
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("我是动态代理!");
if (method.getName().equalsIgnoreCase("doSomething")){
System.out.println("插入点什么??");
}
Object result=method.invoke(object,objects);
return result;
}
打印结果为
我是动态代理!
插入点什么??
买肉!
本质上,这就是aop,具体aop的东西自行搜索吧,这里扯远了。。
总结
代理模式是常用的结构型设计模式之一,它为对象的间接访问提供了一个解决方案,可以对对象的访问进行控制
优点
- 可以协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性