美文网首页
代理模式

代理模式

作者: yangzai | 来源:发表于2018-01-20 12:32 被阅读8次
    • 定义:
      为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
    • UML:


      image.png
    • 模型:
      明星->经纪人
      //抽象出明星与经纪人行为
    public interface Star {
        void confer();//面谈
        void signContract();//签合同
        void bookTicket();//订票
        void sing();//唱歌
        void collectMoney();//收尾款
    }
    

    //明星

    public class RealStar implements Star{
        @Override
        public void confer() {
            System.out.println("RealStar.confer()");
        }
        @Override
        public void signContract() {
            System.out.println("RealStar.signContract()");
        }
        @Override
        public void bookTicket() {
            System.out.println("RealStar.bookTicket()");
        }
        @Override
        public void sing() {
            System.out.println("张学友.sing()");//真实角色的操作:真正的业务逻辑
        }
        @Override
        public void collectMoney() {
            System.out.println("RealStar.collectMoney()");
        }
    }
    

    //经纪人:

    public class ProxyStar implements Star{
        private Star star;//真实对象的引用(明星)
        @Override
        public void confer() {
            System.out.println("ProxyStar.confer()");
        }
        @Override
        public void signContract() {
            System.out.println("ProxyStar.signContract()");
        }
        @Override
        public void bookTicket() {
            System.out.println("ProxyStar.bookTicket()");
        }
        @Override
        public void sing() {
            star.sing();//真实对象的操作(明星唱歌)
        }
        @Override
        public void collectMoney() {
            System.out.println("ProxyStar.collectMoney()");
        }
        public ProxyStar(Star star) {//通过构造器给真实角色赋值
            this.star = star;
        }
    }
    

    //测试

    public static void main(String[] args) {
        Star real = new RealStar();
        Star proxy = new ProxyStar(real);
        proxy.confer();
        proxy.signContract();
        proxy.bookTicket();
        proxy.sing();//真实对象的操作(明星唱歌)
        proxy.collectMoney();
    }
    

    通过代理对象,明星与经纪人的职责清晰, 明星只需关注自身逻辑实现,非业务逻辑部分,后期通过经纪人完成即可。例如跟各个公司洽谈合作事宜由代理人完成即可。

    • 以上代理是静态代理,对于 静态语言,java、c、c++等,他们都需要编译再执行。静态代理是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
      动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
    • java 中的动态代理实现需要以下几步:
      • 1.定义代理对象的行为
      • 2.实现InvocationHandler接口
      • 3.使用Proxy.newProxyInstance创建代理对象
      • 4.调用代理对象方法。
        //定义代理对象的行为
    public interface PersonBean {
        String getName();
        String getGender();
        String getInterests();
        int getHotOrNotRating();
        void setName(String name);
        void setGender(String gender);
        void setInterests(String interests);
        void setHotOrNotRating(int rating);
    }
    

    //真实对象

    public class PersonBeanImpl implements PersonBean{
        String name;
        String gender;
        String interests;
        int rating;
        int ratingcount=0;
        @Override
        public String getName() {
            return name;
        }
        @Override
        public String getGender() {
            return gender;
        }
        @Override
        public String getInterests() {
            return interests;
        }
        @Override
        public int getHotOrNotRating() {
            if(ratingcount==0)      return 0;
            return (rating/ratingcount);
        }
        @Override
        public void setName(String name) {
            this.name=name;
        }
        @Override
        public void setGender(String gender) {
            this.gender=gender;
        }
        @Override
        public void setInterests(String interests) {
            this.interests=interests;
        }
        @Override
        public void setHotOrNotRating(int rating) {
            this.rating=rating;
            ratingcount++;
        }
    }
    

    //实现InvocationHandler接口

    public class OwnerInvocationHandler implements InvocationHandler{
            //被代理对象
        PersonBean person;
        public OwnerInvocationHandler(PersonBean person){
            this.person=person;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if(method.getName().startsWith("get")){
                            //调用被代理对象行为
                return method.invoke(person,args);
            }else if(method.getName().equals("setHotOrNotRating")){
                return new IllegalAccessException();
            }else if(method.getName().startsWith("set")){
                return method.invoke(person,args);
            }
            return null;
        }
    }
    

    //使用

    public class MatchService {
        public MatchService() {
            PersonBean joe = getPersonInfo("joe", "male", "running");
            PersonBean OwnerProxy = getOwnerProxy(joe);
            System.out.println("Name is " + OwnerProxy.getName());
            System.out.println("Interests is " + OwnerProxy.getInterests());
            OwnerProxy.setInterests("Bowling");
            System.out.println("Interests are " + OwnerProxy.getInterests());
            OwnerProxy.setHotOrNotRating(50);
            System.out.println("Rating is " + OwnerProxy.getHotOrNotRating());
            OwnerProxy.setHotOrNotRating(40);
            System.out.println("Rating is " + OwnerProxy.getHotOrNotRating());
            System.out.println("**************");
        }
        PersonBean getPersonInfo(String name, String gender, String interests) {
            PersonBean person = new PersonBeanImpl();
            person.setName(name);
            person.setGender(gender);
            person.setInterests(interests);
            return person;
        }
    
        PersonBean getOwnerProxy(PersonBean person){
            return (PersonBean) Proxy.newProxyInstance(person.getClass()
                    .getClassLoader(), person.getClass().getInterfaces(),
                    new OwnerInvocationHandler(person));
        }
    //测试
        public static void main(String[] args) {    
            MatchService mMatchService=new MatchService();
        }
    }
    

    通过上述代码,我们不需要手动创建代理类,java在运行时根据我们传入的行为组接口,帮我们动态创建了一个proxy,在调用行为组方法是,proxy会调用InvocationHandler的invoke方法,在这个方法里我们可以调用真实对象的方法,或者添加一些其他逻辑,比如方法前、后打印时间。

    相关文章

      网友评论

          本文标题:代理模式

          本文链接:https://www.haomeiwen.com/subject/wrzzoxtx.html