Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 代理模式和装饰模式之间的差异_Oop_Design Patterns_Decorator_Proxy Pattern - Fatal编程技术网

Oop 代理模式和装饰模式之间的差异

Oop 代理模式和装饰模式之间的差异,oop,design-patterns,decorator,proxy-pattern,Oop,Design Patterns,Decorator,Proxy Pattern,你能解释一下代理和装饰的区别吗 我看到的主要区别是,当我们假设代理使用组合而装饰器使用聚合时,似乎很清楚,通过使用多个(一个或多个)装饰器,您可以修改/添加功能到预先存在的实例(装饰),然而,代理拥有自己的代理类的内部实例,并向其委托添加一些附加功能(代理行为) 问题是-使用聚合创建的代理仍然是代理还是装饰器?是否允许(根据GoF模式中的定义)创建具有聚合的代理?装饰器模式侧重于向对象动态添加函数,而代理模式侧重于控制对对象的访问 编辑:- 代理和真实主题之间的关系通常在编译时设置,代理以某种方

你能解释一下代理和装饰的区别吗

我看到的主要区别是,当我们假设代理使用组合而装饰器使用聚合时,似乎很清楚,通过使用多个(一个或多个)装饰器,您可以修改/添加功能到预先存在的实例(装饰),然而,代理拥有自己的代理类的内部实例,并向其委托添加一些附加功能(代理行为)


问题是-使用聚合创建的代理仍然是代理还是装饰器?是否允许(根据GoF模式中的定义)创建具有聚合的代理?

装饰器模式侧重于向对象动态添加函数,而代理模式侧重于控制对对象的访问

编辑:-


代理和真实主题之间的关系通常在编译时设置,代理以某种方式实例化它,而Decorator在运行时分配给主题,只知道主题的接口

装饰者获取装饰对象的引用(通常通过构造函数),而代理自己负责

Proxy可能根本不会实例化包装对象(这样做是为了防止在不使用对象字段/getter的情况下不必要地访问数据库),而Decorator始终保持指向实际包装实例的链接

代理通常由框架用于添加安全性或缓存/延迟,并由框架构建(而不是由常规开发人员自己构建)


Decorator通常用于开发人员自己根据接口而不是实际类向旧类或遗留类添加新行为(因此它适用于范围广泛的接口实例,代理围绕具体类)。

真正的区别不是所有权(组合与聚合),而是输入信息

装饰者总是通过其委托人。代理可能是他自己创建的,也可能是他自己注射的

但是代理总是知道(更)特定的被委托人类型。换句话说,代理及其被委托人将具有相同的基本类型,但代理指向某个派生类型。装饰器指向它自己的基类型。因此,不同之处在于有关被委派者类型的编译时信息

在动态语言中,如果被委派者被注入,并且恰好具有相同的接口,则没有区别

您的问题的答案是“是”。

关键区别:

public interface Authorization {
    String getToken();
} 
  • 代理提供相同的接口Decorator提供了增强的界面
  • 装饰者代理有不同的目的,但结构相似。两者都描述了如何为另一个对象提供一定级别的间接寻址,并且实现都保留了对转发请求的对象的引用
  • 装饰器可以被视为只有一个组件的退化复合物。然而,装饰者增加了额外的职责——它不用于对象聚合
  • 装饰程序支持递归组合
  • Decorator类声明与LCD(最低类分母)接口的组合关系,该数据成员在其构造函数中初始化
  • 使用代理进行延迟初始化,通过缓存对象和控制对客户端/调用方的访问来提高性能
  • 这篇文章很好地引用了它们的相同点和不同点

    相关SE问题/链接:


    代理和装饰的目的不同,它们关注的是内部实现。代理用于使用远程、跨进程或跨网络对象,就像它是本地对象一样。Decorator用于向原始接口添加新行为


    虽然这两种模式在结构上相似,但代理的大部分复杂性在于确保与源对象的适当通信。另一方面,Decorator专注于添加行为的实现

    花了一段时间才弄明白答案和它的真正含义。举几个例子就可以更清楚地说明这一点

    代理
    首先:

    public interface Authorization {
        String getToken();
    } 
    
    以及:

    还有一个
    授权的调用方
    ,一个相当愚蠢的调用方:

    class Caller {
        void authenticatedUserAction(Authorization authorization) {
            System.out.println("doing some action with : " + authorization.getToken());
        }
    }
    
    到目前为止没有什么不寻常的事,对吧?从某个服务获取令牌,然后使用该令牌。现在,图片中还有一个要求,添加日志记录:这意味着每次都要记录令牌。这种情况很简单,只需创建一个
    代理

    public class LoggingDBAuthorization implements Authorization {
    
        private final DBAuthorization dbAuthorization = new DBAuthorization();
    
        @Override
        public String getToken() {
            String token = dbAuthorization.getToken();
            System.out.println("Got token : " + token);
            return token;
        }
    }
    
    我们将如何使用它

    public static void main(String[] args) {
        LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();
    
        Caller caller = new Caller();
        caller.authenticatedUserAction(loggingDBAuthorization);
    }
    

    请注意,
    loggingdauthorization
    包含
    DBAuthorization
    的一个实例。
    loggingdauthorization
    DBAuthorization
    都实现了
    授权

    • 代理将保存基本接口(
      Authorization
      )的一些具体实现(
      DBAuthorization
      )。换句话说,代理确切地知道被代理的是什么
    装饰者

    它的启动方式与
    代理
    基本相同,有一个界面:

    public interface JobSeeker {
        int interviewScore();
    }
    
    以及它的实施:

    class Newbie implements JobSeeker  {
        @Override
        public int interviewScore() {
            return 10;
        }
    }
    
    现在我们想添加一个更有经验的应聘者,将面试分数加上另一个求职者的分数:

    @RequiredArgsConstructor 
    public class TwoYearsInTheIndustry implements JobSeeker {
    
        private final JobSeeker jobSeeker;
    
        @Override
        public int interviewScore() {
            return jobSeeker.interviewScore() + 20;
        } 
    }
    
    注意我是怎么说的,再加上另一个求职者,而不是新手。
    Decorator
    并不确切地知道它在装饰什么,它只知道被装饰实例的契约(它知道
    求职者
    )。请注意,这与代理不同
    public class TwoYearsInTheIndustry implements JobSeeker {
    
        private final Newbie newbie = new Newbie();
    
        @Override
        public int interviewScore() {
            return newbie.interviewScore() + 20;
        }
    }