A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Inspur 中级黑马   /  2013-9-18 08:50  /  2448 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

今天看了代理一节课,感觉和装饰类差不多,请高手给讲解一下代理和装饰类的区别?

评分

参与人数 1技术分 +1 收起 理由
EYE_SEE_YOU + 1

查看全部评分

5 个回复

倒序浏览
装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;
代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;
装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。总之,使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。   

评分

参与人数 1技术分 +1 收起 理由
EYE_SEE_YOU + 1

查看全部评分

回复 使用道具 举报
      区别在于,代理模式对于被代理的类是固化在代理类中的,而对于装饰器模式,被装饰的类是调用时实例化的,也就是说被装饰的类是可以调用时动态选择的。代理模式中,代理类对被代理的对象有控制权,决定其执行或者不执行。而装饰模式中,装饰类对代理对象没有控制权,只能为其增加一层装饰,以加强被装饰对象的功能,仅此而已。
      对装饰器模式来说,装饰者和装饰客户都实现同一个接口。对代理模式来说,代理类和真实处理的类都实现同一个接口。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。
      总结起来可以说:使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。   
//代理模式
public class Proxy implements Subject{
   
    private Subject subject;
    public Proxy(){
        //关系在编译时确定
        subject =new RealSubject();
    }
    public void doAction(){
        subject.doAction();
    }
}
//代理的客户
public class Client {
        public static void main(String[] args){
             //客户不知道代理委托了另一个对象
             Subject subject = new Proxy();
        }
}

//装饰模式
public class Decorator implements Component {
        private Component component;
        public Decorator(Component component) {
            this.component = component
        }
       public void operation() {
            component.operation();
       }
}

//装饰的客户
public class Client{
        public static void main(String[] args){
            //客户指定了装饰者需要装饰的是哪一个类
            Component component = new Decorator(new ConcreteComponent());
        }
}
回复 使用道具 举报
代理模式是一种很常用的设计模式,其目的是对其他对象提供一种代理以控制对这个对象的访问。

代理模式又分为静态代理和动态代理,静态代理是在程序运行之前就已经存在了代理类,动态代理是程序运行中在内存中生成代理类。
代理模式存在的意义:代理模式是为了解决滥用继承的问题而生的,当想对某个类的功能进行扩充的时候可以使用继承或聚合,很明显用继承的话会造成类泛滥,还有一点就是继承是类具有很强的层级关系的情况下用才好,而紧紧对某个类进行功能的扩充就拿起继承的大刀明显的不合适,那么用聚合呢?聚合是一种松耦合的,用聚合创建的代理类就是静态代理,还有更好的代理是动态代理。

动态代理自己实现其实也很简单,不过JDK提供了方便的解决方案。
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
这两个东东就是为动态代理而生的

Java代码
1.package design.proxy.hello;  
2./**  
3. * @author 作者 E-mail: jqsl2012@163.com
4. * @version 创建时间:2012-2-2 下午03:57:56 <br>
5. */  
6.public interface Hello {  
7.    void say();  
8.}  

Java代码
1.package design.proxy.hello;  
2.  
3./**
4. * @author 作者 E-mail: jqsl2012@163.com
5. * @version 创建时间:2012-2-2 下午03:58:10 <br>
6. * 被代理的类
7. */  
8.public class HelloImpl implements Hello {  
9.  
10.    public void say() {  
11.        System.out.println("say");  
12.    }  
13.}  

Java代码
1.package design.proxy.hello;  
2.  
3.import java.lang.reflect.InvocationHandler;  
4.import java.lang.reflect.Method;  
5.import java.lang.reflect.Proxy;  
6.  
7./**
8. * @author 作者 E-mail: jqsl2012@163.com
9. * @version 创建时间:2012-2-2 下午03:54:45 <br>
10. * 动态代理
11. */  
12.public class HelloProxy {  
13.    public static Object newProxyInstance(final Object target) {  
14.        InvocationHandler h = new InvocationHandler() {  
15.  
16.            public Object invoke(Object proxy, Method method, Object[] args)  
17.                    throws Throwable {  
18.                before();  
19.                Object result = method.invoke(target, args);  
20.                after();  
21.                return result;  
22.            }  
23.        };  
24.        return Proxy.newProxyInstance(target.getClass().getClassLoader(),  
25.                target.getClass().getInterfaces(), h);  
26.    }  
27.  
28.    private static void before() {  
29.        System.out.println("before");  
30.    }  
31.  
32.    private static void after() {  
33.        System.out.println("after");  
34.    }  
35.}  

Java代码
1.package design.proxy.hello;  
2./**  
3. * @author 作者 E-mail: jqsl2012@163.com
4. * @version 创建时间:2012-2-2 下午03:57:44 <br>
5. *  
6. */  
7.public class Test {  
8.    public static void main(String[] args) {  
9.        /*
10.         * 代理模式
11.         */  
12.        Hello proxy = (Hello) HelloProxy.newProxyInstance(new HelloImpl());  
13.        proxy.say();  
14.    }  
15.}  
-----------------------------分割线----------------------------------
上面是代理模式,其实装饰模式和代理模式极为相似
相同点:都是为被代理(被装饰)的类扩充新的功能。
不同点:代理模式具有控制被代理类的访问等性质,而装饰模式紧紧是单纯的扩充被装饰的类。所以区别紧紧在是否对被代理/被装饰的类进行了控制而已。

Java代码
1.package design.staticProxy;  
2./**  
3. * @author 作者 E-mail: jqsl2012@163.com
4. * @version 创建时间:2012-2-3 下午10:10:43 <br>
5. */  
6.public interface InputStream {  
7.    void read();  
8.}  

Java代码
1.package design.staticProxy;  
2./**  
3. * @author 作者 E-mail: jqsl2012@163.com
4. * @version 创建时间:2012-2-3 下午10:11:16 <br>
5. */  
6.public class FileInputStream implements InputStream{  
7.  
8.    public void read() {  
9.        System.out.println("FileInputStream.read");  
10.    }  
11.  
12.}  


Java代码
1.package design.staticProxy;  
2.  
3./**
4. * @author 作者 E-mail: jqsl2012@163.com
5. * @version 创建时间:2012-2-3 下午10:11:50 <br>
6. * 代理/装饰类具有和被代理/被装饰的类相同的接口
7. */  
8.public class BufferedInputStream implements InputStream {  
9.    protected InputStream in;  
10.  
11.    public BufferedInputStream(InputStream in) {  
12.        this.in = in;  
13.    }  
14.  
15.    public void read() {  
16.        //加入控制代码就是代理,否则单纯的扩充功能就是装饰模式  
17.        if(true){  
18.            System.out.println("BufferedInputStream.read");  
19.        }  
20.        this.in.read();  
21.    }  
22.}  


Java代码
1.package design.staticProxy;  
2.  
3./**
4. * @author 作者 E-mail: jqsl2012@163.com
5. * @version 创建时间:2012-2-3 下午10:13:20 <br>
6. */  
7.public class Test {  
8.    public static void main(String[] args) {  
9.        BufferedInputStream buffIn = new BufferedInputStream(new FileInputStream());  
10.        buffIn.read();  
11.    }  
12.}  


很明显,装饰模式和静态代理极为相似。设计模式里面有许多模式都看起来很相似,要区分估计得从目的上去区分了。
回复 使用道具 举报
楼主可以看看下面的总结:

装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;
代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;


装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能

二者的实现机制确实是一样的,可以看到他们的实例代码重复是很多的。但就语义上说,这两者的功能是相反的,模式的一个重要作用是简化其他程序员对你程序的理解,

你在一个地方写装饰,大家就知道这是在增加功能,你写代理,大家就知道是在限制,

虽然代码很可能相同,但如果你都叫他们装饰,别人会很迷惑的。
回复 使用道具 举报
本帖最后由 yting_xmei1129 于 2013-9-24 23:16 编辑

这两个设计模式看起来很像。         
  对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个 接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。

       然而,实际上,在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。

        我们可以用另外一句话来总结这些差别:使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。  

希望可以帮到楼主、、、

The you smile until forever 、、、、、、、、、、、、、、、、、、、、、


回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马