Head First 设计模式 —— 13. 代理 (Proxy

2021-01-16  本文已影响0人  满赋诸机

思考题

如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435

思考题

远程调用程序应该完全透明吗?这是个好主意吗?这个方法可能会产生什么问题? P435

代理模式

为另一个对象提供一个替身或占位符以控制对这个对象的访问。 P460

13. 代理模式

特点

缺点

代理模式和装饰器模式 P471

代理模式和适配器模式的区别 P471

思考题

class ImageProxy implements Icon {
    // 实例变量构造器在这里
    public int getIconWidth() {
        if (imageIcon != null) {
            return imageIcon.getIconWidth();
        } else {
            return 800;
        }
    }
    
    public int getIconHeight() {
        if (imageIcon != null) {
            return imageIcon.getIconHeight();
        } else {
            return 600;
        }
    }
    
    public void paintIcon(final Component c, Graphics g, int y, int y) {
        if (imageIcon != null) {
            imageIcon.paintIcon(c, g, x, y);
        } else {
            g.drawString("Loading CD cover, please wait...", x + 300, y + 190);
            // 实例化 imageIcon 获取图片
        }
    }
}

以上为 CD 封面虚拟代理, ImageProxy 类似乎有两个,由条件语句控制的状态。你能否用另一个设计模式清理这样的代码?你要如何重新设计 ImageProxyP468

思考题

NonOwnerInvocationHandler 工作的方式除了它允许调用 setHotOrNotRating() 和不允许调用其他 set 方法之外,与 NonOwnerInvocationHandler 是很相似的。请写出 NonOwnerInvocationHandler 的代码: P482

import java.lang.reflect.*;

public class NonOwnerInvocationHandler implements InvocationHandler {
    PersonBean person;
    
    public NonOwnerInvocationHandler(PersonBean person) {
        this.person = person;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
        try {
            String methodName = method.getName();
            if (methodName.startsWith("get")) {
                return method.invoke(person, args);
            } else if(methodName.equals("setHotOrNotRating")) {
                return method.invoke(person, args);
            } else if(methodName.startsWith("set")) {
                throw new IllegalAccessException();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}

思考题

创建动态代理所需要的代码很短,请你写下 getNonOwnerProxy() ,该方法会返回 NonOwnerInvocationHandler 的代理。更进一步,请写下 getProxy() 方法,参数是 handlerperson ,返回值是使用此 handler 的代理。 P483

PersonBean getNonOwnerProxy(PersonBean person) {
    return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new NonOwnerInvocationHandler(person));
}

PersonBean getProxy(InvocationHandler handler, PersonBean person) {
    return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);
}

思考题

如何知道某个类是不是代理类? P486

思考题

能传入 newProxyInstance() 的接口类型,有没有什么限制?

思考题

配对下列模式和描述: P487

代理模式:包装另一个对象,并控制对它的访问

外观模式:包装许多对象以简化它们的接口

装饰器模式:包装另一个对象,并提供额外的行为

适配器模式:包装另一个对象,并提供不同的接口

所思所想

上一篇下一篇

猜你喜欢

热点阅读