早点知道它,我可能就有对象了:代理模式

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情


如题目所说,可能我早点知道代理模式,我就是个有对象的人了。不过现在已经有对象了,今天是对着女朋友写文章的一天。给大家看看对象的照片:

开个玩笑,其实刘涛是我非常喜欢的明星,她主演的电视剧《欢乐颂》不知道大家有没有看过,在这部剧中有这么一个剧情,樊胜美的父亲住院马上要手术,但是没钱,本来是安迪(刘涛演的)处理这件事,但是安迪经受不住,所以请魏总帮她处理手术费的事。这个剧情里,我们重点关注三个点:第一个,本来应该处理樊家事是安迪;第二个,魏总跟樊家本来没有一点关系;第三就是处理樊家的事。我们画成图可能会更好理解一点。

这呢,我们发现了多了一个中间者魏总,他的角色就是代理,就是我们本文要说的主体,代理模式,就是为其他对象提供一种代理以控制这个对象的访问。把上面的图套一下就是:安迪找了代理魏总去处理樊家的事。安迪把处理樊家事情的权利“复制”给了魏总一份。这样安迪跟魏总就有了共同行为,都能处理樊家的事。

哎,小林。今天讲策略模式呢!你跑远了,快回来!

“对不起,对不起,我没有学过马学,年轻人不懂武德,见谅!”

今天的案例非常的奈斯,主题是如何表白。每个男生都会有喜欢的女生,这个女生在他们心里叫做Goddess,如文章标题,小林有喜欢的人吗?废话,肯定有啊,但是小林之前没学过代理模式,所以错过了Goddess!希望大家好好把握,学好代理模式,早日迎娶白富美,走向人生巅峰。

用户故事:我想要表白心中的女神,我如何做?

一场精心的表白计划如下:

  1. 给女生送抱枕,说是柏豪送的
  2. 叫女神数学题,说是柏豪想出来的方法,柏豪让教的
  3. 给女神讲笑话,说是柏豪找的笑话,让其代讲

表白现场

小林:小美,你好。我是高三666,6翻了班的小林,这是我们班柏豪送你的抱枕,他想跟你认识一下。看在我平时给你讲数学题的份上你就收了吧。

小美:好,我刚好有道数学题难住了,等下能教教我吗?那抱枕我就收下了,谢谢。

小林(笑逐颜开):没问题,小美。柏豪刚教我几种解题技巧,让我教给你,这下又帮柏豪一件大事。

小美:害,这怎么好意思呢。我们先学习把,你给我说说第26页第1题那个题怎么做...

过了几天

小林:小美,早上看你不太开心,柏豪找了个笑话,让我讲给你听。

小美:好吧,最近有点烦心事,你给我说说吧,让我开心开心。

笑话讲完后,两个人哈哈大笑,小美非常的开心,此时小美放大招了

小美:小林,柏豪这个名字是不是你编出来的?你们班都没这个人,送抱枕,将数学题,讲笑话,你都说成是柏豪。你这是给别人做嫁衣,笨蛋!其实我早就察觉出来你对我的好了,我也挺喜欢你的。

小林(直接上天):我没听错吧?太惊喜了,小美你能把刚才最后一句话再说一百遍吗!

故事的结局以小林,小美牵手为结局,是不是非常的奈斯。

这里举这个例子是为了配合下面的代码,所以生活中大家不要轻易尝试哈哈哈,试的时候记得说一个不存在的名字,要是真有这个名字,可能真就给别人做嫁衣了。\

这里的案例目的是为了讲清楚什么是代理,故事跟实际代码会有点差距,但是小林相信大家可以理解。(如果有问题留言或评论,再补充解释说明)

代码实现

女神类

@Getter
@Setter
public class Goddess {
    // 女神的名字
    String name;

    public Goddess(String name) {
        this.name = name;
    }
}
复制代码

分析下,为什么要有这个接口。首先代理代理,代理者是否应该拥有被代理者的等同的功能?比如我代理了小林烧鸡,代理后小林可以卖鸡腿,而我不行,这就不能称之为代理了。所以我们将相同的行为抽成一个接口。(对应欢乐颂中就是,处理樊家事这个行为就是安迪跟魏总都有的相同的行为)

// 代理接口
public interface IGiveGift {

    // 送抱枕
    void GivePillow();

    // 教数学技巧
    void GiveMathQuestion();

    // 讲笑话
    void GiveTellJoke();
}
复制代码

追求者类实现代理接口

// 追求者类实现代理接口
public class Pursuit implements IGiveGift {

    public Goddess goddess;

    public Pursuit(Goddess goddess) {
        this.goddess = goddess;
    }

    @Override
    public void GivePillow() {
        System.out.println(goddess.getName() + "我送你一个杨洋抱枕");
    }

    @Override
    public void GiveMathQuestion() {
        System.out.println(goddess.getName() + "我教你做数学题");
    }

    @Override
    public void GiveTellJoke() {
        System.out.println(goddess.getName() + "我给你讲笑话");
    }
}
复制代码

代理类,追求者拥有的送抱枕,教做数学题,讲笑话行为,都可以“代理”过来。然后在类中维护一个追求者对象,那么就可以用这个追求者对象去做一些事,比如帮追求者送抱枕等。

public class Proxy implements IGiveGift {
    // 内部维护一个追求者对象
    private Pursuit pursuit;

    public Proxy(Goddess goddess) {
        pursuit = new Pursuit(goddess);
    }

    @Override
    public void GivePillow() {
        pursuit.GivePillow();
    }

    @Override
    public void GiveMathQuestion() {
        pursuit.GiveMathQuestion();
    }

    @Override
    public void GiveTellJoke() {
        pursuit.GiveTellJoke();
    }
}
复制代码

Main

public class MainTest {
    public static void main(String[] args) {
        Goddess goddess = new Goddess("女一号");
        Proxy xiaoLin = new Proxy(goddess);
        xiaoLin.GivePillow();
        xiaoLin.GiveMathQuestion();
        xiaoLin.GiveTellJoke();
    }
}
复制代码

看一下MainTest类中的代码我们通过代理类Proxy来创建一个对象,小林实际上只是一个代理,真正送小美抱枕的代理类中的Pursuit对象!看下运行结果:

想了许久决定在每篇设计到设计模式的文章中,加上对应代码的UML类图,如果你想考量你是否掌握了该设计模式,这或许就是标准,只要你能画出正确的UML类图即可。(关于UML类图可能很多人没有接触后,以后抽空会出一篇文章专门讲UML类图)

本次设计模式案例UML类图

猜你喜欢

转载自juejin.im/post/7104279523822469156