面试官问:代理模式和装饰者模式有啥区别

今天面试聊到了模式。

面试官问:装饰者模式了解吗,讲一下?

我:blabla...

面试官:那代理模式呢?

我:blabla.....(说完感觉怎么都一样呢)

果然,面试官又问了:那两者有什么区别呢?

我: ....懵.........懵.........懵.........懵.........

 

 

 

首先呢来看一下定义。

一、代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问。代理模式是一项基本的设计技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上也采用了代理模式。

面试官问:代理模式和装饰者模式有啥区别_第1张图片

在代理模式中主要包含三个角色:

  1. 抽象主题角色Subject:是真实主题和代理主题的共同接口,以便在任何可以使用真实主题的地方都可以使用代理主题。
  2. 代理主题角色Proxy Subject:也叫做委托类、代理类,该角色负责控制对真实主题的引用,负责在需要的时候创建或删除真实主题对象,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
  3. 真实主题角色Real Subject:也叫做被委托角色、被代理角色,是业务逻辑的具体执行者。

二、装饰者模式

装饰者模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。

面试官问:代理模式和装饰者模式有啥区别_第2张图片

装饰模式有以下4个角色。

  1. 抽象构件(Component)角色:该角色用于规范需要装饰的对象(原始对象)。
  2. 具体构件(Concrete Component)角色:该角色实现抽象构件接口,定义一个需要装饰的原始类。
  3. 装饰(Decorator)角色:该角色持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
  4. 具体装饰(Concrete Decorator)角色:该角色负责对构件对象进行装饰。

 

三、区别

从定义上看似乎能够回答面试官的问题,一个是用于实现访问控制,一个是增加功能。可是。。访问控制是什么,增加功能又是怎么样的?到底啥是佩琪,还是要搞清楚些,看一些具体的例子来了解下。

3.1 访问控制 -- 代理模式

// 抽象主题
interface AbstractSubject{
    void doAction();
}

// 真实主题
class RealSubject implements AbstractSubject{
    @Override
    public void doAction() {
        System.out.println(" Real Action ");
    }
}

// 代理主题
class ProxySubject implements AbstractSubject{
    private AbstractSubject subject;

    public ProxySubject(){
        this.subject = new RealSubject();
    }

    @Override
    public void doAction() {
        System.out.println(" Before Proxy do Action");
        subject.doAction();
        System.out.println(" Before Proxy do Action");
    }
}

// 客户端
public class Client{

    public static void main(String[] args) {
        AbstractSubject subject = new ProxySubject();
        subject.doAction();
    }
}

3.2 功能扩展 -- 装饰者模式

// 抽象构件
interface Human{
    void eat();
}

// 具体构件
class Baby implements Human{

    @Override
    public void eat() {
        System.out.println("Baby eating");
    }
}

// 装饰角色
class Guardian implements Human{
    private Human human;

    public Guardian(Human h){
        human = h;
    }

    @Override
    public void eat() {
        human.eat();
    }
}

// 具体装饰角色
class Parent extends Guardian{

    public Parent(Human h) {
        super(h);
    }

    @Override
    public void eat() {
        System.out.println("Wash hands for baby");
        super.eat();
    }
}



// 客户端
Baby baby = new Baby();
Human human = new Parent(baby);
human.eat();

四、总结

等待,看完例子怎么感觉又似懂非懂了呢。不是说一个控制访问,一个增强功能吗,为什么都是中间类和目标类实现了相同的接口,在调用目标类时增加了自己的方法呢?好像确实又懵了。

面试官问:代理模式和装饰者模式有啥区别_第3张图片

其实,代理模式的访问控制主要在于对目标类的透明访问,也就是说我们不需要知道目标类的具体情况,只需要知道代理类可以帮助我们完成想要的功能就对了;而对于装饰者模式,我们是有一个目标类的对象的,比如例子中的baby,这个对象可以完成特定的功能(eat),但是不能满足我们的要求,所以需要对其进行增强(饭前洗手)。

也就是说,在代理模式中,目标类对于客户端是透明的,由代理类隐藏其具体信息并响应客户端请求;而装饰者中客户端对特定的目标类对象进行增强。所以,代理类与真实对象的关系常在编译时就确定,而装饰者在运行时递归构造。

 

 

 

----------

终于搞明白了这两个相似的设计模式的关系,好像智商又占领了高地,就是脚有点麻   ------

 

你可能感兴趣的:(Design,Pattern,设计模式,装饰者模式,代理模式)