java设计模式-代理模式

137 阅读6分钟

代码参考(更详细,这里为了博客简洁,代码去了一些注释)  github.com/zhang-xiaox…

 1静态代理(接口代理)

需求(干什么):对明星唱歌的业务流程进行代理,而明星唱歌还是交由明星自己唱歌,这个流程把唱歌分成2部分了,1:歌手尽管唱歌,2:代理公司负责打杂(面谈,签合同,订票,收钱),对被代理的歌手来说,他解放了,相当于增强了,不用自己面谈,签合同什么的,对代理公司来说,我就打杂就行了,赚点差价,唱歌不行,只好请歌手(无法全程代理),各司其职.

先明确所有流程下来需要干那些事情,使用接口明确一下(面向接口编程哈)

package com.demo.proxy.staticproxy;
/**
 * Star:代理接口,这里规定了整个业务需要完成的事情
 * (万事万物接口开头,面向接口编程,先明确要干什么,怎么干是后面实现类的事情,这样有利于解耦,
 * 比如同样是面谈的实现,需要换个面谈方式那不是还得修改代理类?这里直接定义成接口,那么代理要换个代理只需要换个代理实现类就行了
 * 不需要对代理接口进行修改,达到开闭原则,开放拓展,但是修改接口这个代理接口Star不允许)
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */
public interface Star {
	/**
	 * 面谈
	 */
	void confer();
	/**
	 * 签合同
	 */
	void signContract();
	/**
	 * 订票
	 */
	void bookTicket();
	/**
	 * 唱歌
	 */
	void sing();
	/**
	 * 收钱
	 */
	void collectMoney();

}

 知道了要干什么(上面接口明确了),但是怎么干(实现类)呢,先来个歌手独立开一场演唱会就需要实现所有接口,又当爹又当妈

//package com.demo.proxy.staticproxy;

/**
 * RealStar:一个真实的歌手,在没有代理的情况下需要全部实现,又当爹又当妈
 * (显然不不合理,对歌手来说,除了唱歌,其他打杂的事情,面谈,签合同什么的都没有必要去做)
 *
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */
public class RealStar implements Star {
    /**
     * 面谈
     */
    @Override
    public void confer() {
        //可以做空实现
        System.out.println("真实对象执行面谈===>RealStar.confer()");
    }

    /**
     * 签合同
     */
    @Override
    public void signContract() {
        //可以做空实现
        System.out.println("真实对象执行签合同===>RealStar.confer()");
    }

    /**
     * 订票
     */
    @Override
    public void bookTicket() {
        //可以做空实现
        System.out.println("真实对象执行订票===>RealStar.confer()");
    }

    /**
     * 唱歌---歌手主要唱歌,其他事情(具体实现),可以不做(就是空实现)
     */
    @Override
    public void sing() {
        //这里唱歌是必须实现的,不然算什么歌手
        System.out.println("真实对象(周杰伦)执行唱歌===>RealStar.confer()");
    }

    /**
     * 收钱
     */
    @Override
    public void collectMoney() {
        //可以做空实现
        System.out.println("真实对象执行收钱===>RealStar.confer()");
    }


}

上面真实歌手在吐槽又当爹又当妈,我作为天使,肯定是来解救你的,并且我不抢你唱歌的光彩,你唱你的,我给你打杂就行了,赚点差价哈哈,下面就是我的自我介绍

//package com.demo.proxy.staticproxy;
/**
 * ProxyStar:代理对象,这是个对某个类(对象)进行增强的
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */

public class ProxyStar implements Star {
	/**
	 * 专业的事情教给专业的人去做,比如在这里就是相当于请歌手唱歌
	 * 注意这里接口做属性,组合比实现类(应用)做属性好的多,因为接口做属性可以请很多歌手唱歌(提现多态),
	 * 但是是实现类做属性(面向实现编程)耦合度太高,换个歌手又得修改这个类,开闭原则是尽量不要修改这个类,所以这里
	 * 是使用Star,而不是 private RealStar star
     *  ---静态代理代理的是接口就是出自这里
	 */
	private Star star;

	/**
	 * 怎么请?这里使用构造方法请,用set方法也行
	 * @param star
	 */
	public ProxyStar(Star star) {
		this.star = star;
	}


	/**
	 * 面谈---代理对象专业的人处理其他事情,相当于打杂,对专业的人来说,相当于增强了
	 */
	@Override
	public void confer() {
		System.out.println("代理面谈===>ProxyStar.bookTicket()");
	}

	/**
	 * 签合同---代理对象专业的人处理其他事情,相当于打杂,对专业的人来说,相当于增强了
	 */
	@Override
	public void signContract() {
		System.out.println("代理签合同===>ProxyStar.bookTicket()");
	}

	/**
	 * 订票---代理对象专业的人处理其他事情,相当于打杂,对专业的人来说,相当于增强了
	 */
	@Override
	public void bookTicket() {
		System.out.println("代理订票===>ProxyStar.bookTicket()");
	}

	/**
	 * 唱歌===专业的人做专业的事
	 */
	@Override
	public void sing() {
		System.out.println("*******代理对象不抢主角光环*******");
		star.sing();
	}

	/**
	 * 收钱---代理对象专业的人处理其他事情,相当于打杂,对专业的人来说,相当于增强了
	 */
	@Override
	public void collectMoney() {
		System.out.println("代理收钱===>ProxyStar.bookTicket()");
	}
}

牛皮都吹出去了,测试一下呗,合作愉快下次继续哟,亲,记得给个五星好评哟

package com.demo.proxy.staticproxy;
/**
 * Client:客户端   静态代理测试
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */

public class Client {
	public static void main(String[] args) {
		System.out.println("----------------------测试静态代理-------------------");
		Star real = new RealStar();
		Star proxy = new ProxyStar(real);
		
		proxy.confer();
		proxy.signContract();
		proxy.bookTicket();

		//这里代理对象持有真实对象的一切,比如让代理的真实对象周杰伦唱歌,对周杰伦这个对象来说,他功能增强了,
		//上面的操作和下面的操作都算增强
		proxy.sing();

		proxy.collectMoney();
		
	}
}

 演唱会全程回顾如下:

2动态代理(代理对象)  Star接口还是那个接口(上文静态代理的),RealStar接口还是那个接口(上文静态代理的)

 

一个对JDK调用处理器的实现类
//package com.demo.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * StarHandler:这是一个对JDK调用处理器的实现类,用于被代理的一个类,利用这个类可以JDK为其生成一个代理对象
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */
public class StarHandler implements InvocationHandler {
	/**
	 * 这里仍然是要代理接口的,相当于唱歌业务流程始终是要有公司接单,实现演唱会,只是这里不是代理类直接接单
	 * 由评审团StarHandler来评估先代理
	 */
	Star realStar;

	/**
	 * 构造方法注入"演唱会订单"
	 * @param realStar
	 */
	public StarHandler(Star realStar) {
		this.realStar = realStar;
	}

	/**
	 * 重写JDK代理方法(使用反射生成响应对象)
	 * @param proxy 评估后具备代理资格的代理公司对象
	 * @param method 方法(真是对象需要执行的操作,唱歌)
	 * @param args
	 * @return
	 * @throws Throwable
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 评估后具备代理资格的代理公司对象
		Object object = null;
		
		System.out.println("真正的方法执行前!");
		System.out.println("面谈,签合同,预付款,订机票");

		//用反射的方式获取方法名称
		if(method.getName().equals("sing")){
			object = method.invoke(realStar, args);
		}
		
		System.out.println("真正的方法执行后!");
		System.out.println("收尾款");
		return object;
	}

}
模拟动态生成的代理的类
//package com.demo.proxy.dynamicproxy;

/**
 * ProxyStar:模拟动态生成的代理的类
 *
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */
public class ProxyStar implements Star {
    /**
     * 注入代理处理器类(动态代理是代理类这句话,就是来自这里),在静态代理这里是直接注入的private Star star 接口,就是代理的是接口
     * ---一句话代理类,这个类是动态的哈
     */
    StarHandler handler;

    /**
     * 使用构造方法实现注入,set方法也行,不赘述
     *
     * @param handler
     */
    public ProxyStar(StarHandler handler) {
        this.handler = handler;
    }

    /**
     * 面谈
     */
    @Override
    public void confer() {
        //		handler.invoke(this,当前方法 , args);
    }

    /**
     * 签合同
     */
    @Override
    public void signContract() {
        //		handler.invoke(this,当前方法 , args);
    }

    /**
     * 订票
     */
    @Override
    public void bookTicket() {
        //		handler.invoke(this,当前方法 , args);
    }

    /**
     * 唱歌
     */
    @Override
    public void sing() {
        //		handler.invoke(this,当前方法 , args);
    }

    /**
     * 收钱
     */
    @Override
    public void collectMoney() {
        //		handler.invoke(this,当前方法 , args);
    }


}

 客户端测试

package com.demo.proxy.dynamicproxy;

import java.lang.reflect.Proxy;
/**
 * Client:客户端   测试动态代理
 * @author zhangxiaoxiang
 * @date 2019/8/9
 */

public class Client {
	public static void main(String[] args) {
		System.out.println("----------测试的动态代理-----------");
		Star realStar = new RealStar();
		//代理类
		StarHandler handler = new StarHandler(realStar);
		//利用JDK生成代理对象
		Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 
				new Class[]{Star.class}, handler);
		proxy.sing();
	}
}

 动态代理的演唱会事故现场

3:cglib代理,请参考www.cnblogs.com/boboxing/p/…

 

总结:AOP面向切面编程早晚会用的一种模式,自己去体会3个模式的优缺点,然后瞎搞几下.

友情链接:blog.csdn.net/Goskalrie/a…