Head First Design Patterns -代理模式

什么是代理模式

代理模式为另一个对象提供替身或者占位符,以便控制客户对对象的访问,管理访问的方式有很多种。例如远程代理、虚拟代理、保护代理等。

远程代理:管理客户和远程对象之间的交互。

虚拟代理:控制访问实例化开销大的对象。

保护代理:基于调用者,控制对对象方法的调用。

类图

代码

案例:防止对person类的访问中,访问了不该访问的方法

以保护代理为例,主要是基于java内置的动态代理,来控制对对象方法的调用,其类图如下:

Person接口

java 复制代码
public interface Person {
    String getName();

    String getGender();

    String getInterests();

    int getGeekRating();

    void setName(String name);

    void setGender(String gender);

    void setInterests(String interests);

    void setGeekRating(int rating);
}

Person实现类

java 复制代码
public class PersonImpl implements Person{
    String name;
    String gender;
    String interests;
    int rating;
    int ratingCount = 0;

public PersonImpl(String name, String gender, String interests, int rating, int ratingCount) {
        this.name = name;
        this.gender = gender;
        this.interests = interests;
        this.rating = rating;
        this.ratingCount = ratingCount;
    }

@Override
public String getName() {
   return name;
}

@Override
public void setName(String name) {
   this.name = name;
}

@Override
public int getGeekRating() {
   if (ratingCount == 0) {
       return 0;
   } else {
       return rating  / ratingCount;
   }
}

@Override
public void setGeekRating(int rating) {
   this.rating += rating;
   ratingCount++;
}

@Override
public void setGender(String gender) {
   this.gender = gender;
}

@Override
public String getGender() {
   return gender;
}

@Override
public String getInterests() {
   return interests;
}

@Override
public void setInterests(String interests) {
   this.interests = interests;
}

NonOwnerInvocationHandler类

java 复制代码
//InvocationHandler
public class NonOwnerInvocationHandler implements InvocationHandler {
    Person person;

    public NonOwnerInvocationHandler(Person person) {
        this.person = person;
    }

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        if (method.getName().startsWith("get")) {
            return method.invoke(person, args);
        } else if (method.getName().equals("setGeekRating")) {
            return method.invoke(person, args);
        } else if (method.getName().startsWith("set")) {
            throw new Throwable();
        }
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

    return null;
}
}

OwnerInvocationHandler类

java 复制代码
public class OwnerInvocationHandler implements InvocationHandler {
    Person person;

    public OwnerInvocationHandler(Person person) {
        this.person = person;
    }

// 
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   try {
       if (method.getName().startsWith("get")) {
           return method.invoke(person, args);
       } else if (method.getName().equals("setGeekRating")) {
           throw new Throwable();
       } else if (method.getName().startsWith("set")) {
           return method.invoke(person, args);
       }
   } catch (InvocationTargetException e) {
       e.printStackTrace();
   }

   return null;
}
}

测试:

java 复制代码
public class Test {
    public static void main(String[] args) {
        Person kang = new PersonImpl("kwb", "boy", "ball", 1, 3);
        Person owner = getProxy.getOwnerProxy(kang);

        System.out.println(owner.getName());
    }
}

区别

装饰器模式为对象加上行为,而代理则是控制访问。

相关推荐
Pasregret14 分钟前
访问者模式:分离数据结构与操作的设计模式
数据结构·设计模式·访问者模式
Aniugel3 小时前
JavaScript高级面试题
javascript·设计模式·面试
不当菜虚困3 小时前
JAVA设计模式——(四)门面模式
java·开发语言·设计模式
Niuguangshuo3 小时前
Python设计模式:MVC模式
python·设计模式·mvc
Lei活在当下4 小时前
【现代 Android APP 架构】01. APP 架构综述
android·设计模式·架构
前端大白话4 小时前
震惊!90%前端工程师都踩过的坑!computed属性vs methods到底该怎么选?一文揭秘高效开发密码
前端·vue.js·设计模式
前端大白话4 小时前
前端必看!figure标签在响应式图片排版中的王炸操作,grid/flex布局实战指南
前端·设计模式·html
ApeAssistant4 小时前
Spring + 设计模式 (十四) 行为型 - 观察者模式
spring·设计模式
ApeAssistant4 小时前
Spring + 设计模式 (十三) 行为型 - 策略模式
spring·设计模式
摘星编程5 小时前
并发设计模式实战系列(7):Thread Local Storage (TLS)
设计模式·并发编程