【设计模式】 静态代理

本来是想直接写动态代理的,但是后来想想,要写就写完整吧,而且我相信很多人其实对静态代理的理解也不是很深刻,包括写这篇文章之前的我。

大家一定都听过,艺术源于生活,其实,计算机中的许多思想也是通过生活而来,所以,像计算机领域中的代理模式,肯定也是能在生活中找到映射的。我想了很久,觉得生活中的代购是最能反映代理模式的,所以我决定用代购来让大家理解代理模式(或者让大家了解了解代购

 

一.  简介

我先放一张的结构图

 

上图可以看到,一共有三个角色:

  1. 主题角色(Subject):可以是抽象类也可以是接口,是一个最普通的业务类型定义;

  2. 真实主题角色(RealSubject):被代理的角色,是业务逻辑的具体执行者;

  3. 代理角色(Proxy):它负责对真实主题角色的应用,并且在真实主题角色处理理完毕前后做预处理和善后处理工作。

 

看完后是不是一脸懵逼,我以前学静态代理模式的时候看到这东西也是黑人问号,不过没关系,等大家看完下面再回来看这一节就一目了然了。

 

 

二.  代购与静态代理

好啦,正式开始讲代购啦,咳咳。

我们都知道,一般女生都喜欢名牌包包,但名牌包包有个特点,国外的款式与价格都比国内有优势,所以以前很多多金的妹子都要亲自跑到国外的包包商店买。但是自己去买,不仅费飞机票,还费时间,因此聪明的中国人看到商机,衍生出了一个新的职业:代购。

有了代购,妹子不需要亲自去买了,只需要找代购买了(这里很关键,妹子是找的代购小哥买的,但实际上代购小哥还是需要去到包包商店买,毕竟代购小哥自己没货啊!因此最终提供买包服务的不是代购小哥,而是包包商店!)

 

我们使用代理模式将这个代购的场景用代码描述出来。

我们首先创建一个包包商店的接口(所有包包商店都需要符合这个包包商店接口的规范),接口里面定义了个buyBag的方法:

public interface IBagShop {
    void buyBag(String num);
}

 

接着定义一个包包商店的实现类,这个包包商店类实现了包包商店接口,因此提供了真实的买包服务:

public class BagShop implements IBagShop {
    @Override
    public void buyBag(String money) {
        System.out.println("买了一个价值"+money+"限量款包包!");
    }
}

 

最后定义我们的代购小哥,也要实现包包商店接口(毕竟也是需要提供买包服务给妹子的),且需要引用包包商店类,因为他最终还是需要自己去到包包商店买包包:

public class PurchasingAgent implements IBagShop {
    private IBagShop bagShop;

    public PurchasingAgent(IBagShop bagShop) {
        super();
        this.bagShop = bagShop;
    }

    @Override
    public void buyBag(String num) {
        // 调用包包商店的买服务
        bagShop.buyBag(num);
    }
}

 

三个主要类就完成啦,是不是很简单?没有?那我再给你们看下面这张图,你们就一目了然了:

 

最后我们再写个“妹子”类测测吧:

public class Girl {
    public static void main(String[] args) {
        IBagShop bagShop = new BagShop();
        PurchasingAgent purchasingAgent = new PurchasingAgent(bagShop);
        purchasingAgent.buyBag("10万");
    }
}

这个妹子成功买到这么贵的包包了!

 

 

三.  优点

那代理模式有啥优点呢?

  1. 由代理对象来间接访问目标对象,避免了直接访问目标对象给系统带来复杂杂性;

  2. 通过代理对象对原有对象增强。

第一点我们就不解释了,主要看第二点。

代购小哥尝到了甜头以后,就想吸引更多的妹子来找他买包,于是决定提供售前与售后服务,售前是提供与包包商店的服务员砍价的服务,售后则是附送一些小礼品服务,妹子们看到代购小哥的服务这么好,于是也介绍其他姐妹们来找代购买东西了。你看,这就是代购小哥对包包商店业务的增强。

 

那如何在代码上体现呢?因为是代购小哥提供的服务,因此我们找到代购PruchasingAgent类,在其buy方法中做修改即可:

public class PurchasingAgent implements IBagShop {
    private IBagShop bagShop;

    public PurchasingAgent(IBagShop bagShop) {
        super();
        this.bagShop = bagShop;
    }

    @Override
    public void buyBag(String num) {
        // 售前服务:砍价
        System.out.println(“代购砍了50%的价格,好厉害啊!");
        // 调用包包商店的买服务
        bagShop.buyBag(num);
        // 售后服务:送小礼品
        System.out.println("代购送了价值5元的小礼品,真抠");
    }
}

 

再次启动“妹子”类测试,测试结果为:

 

从上面例子可以看到,代购小哥通过增加售前售后服务增强了包包商店的买包服务业务,因此可以看到静态代理最大的优点就是:通过代理对象对原有业务进行增强。

 

 

四.  缺点

静态方法不满足设计模式原则中的开闭原则(设计模式一共有六大原则,而开闭原则是最重要的一个!纳尼,怪不得会有动态代理)。

那啥是开闭原则?程序对外扩展开放,修改关闭,换句话说,要增加新的功能时,我们可以增加新的模块代码来实现新的需求,但不能修改原有的代码来实现新需求。我们就继续通过代购来看下代理模式如果破坏了开闭原则。

 

经过一段时间,有妹子问代购小哥是否可以在他这里买鞋子,代购小哥虽然没有,但是代购小哥知道鞋子商店在哪啊,于是就接了这单,此后,代购小哥不仅仅代购包包,还代购鞋子了。

为了增加代购小哥的业务,我们如何修改代码呢?

首先我们需要定义一个新的鞋子商店接口,里面定义了一个购买鞋子的方法,然后再建立个实现了鞋子商店接口的鞋子商店类,并实现购买鞋子的方法,这里还是满足开闭原则的,毕竟是新建类和接口嘛。然后最头疼的地方来了,代理类PurchaingAgent需实现鞋子商店接口,且需要引入鞋子商店类,并实现购买鞋子的方法,这些都对源代码进行大量的改动,如果以后代购小哥还想扩展业务,比如代购吃的,代购奶粉,那就要继续改动,这样就违背开闭原则了。

 

好啦,说了这么多,就知道静态代理在实际中用的不多啦,但静态代理还是非常重要的,它是动态代理的基础。动态代理那就更重要啦,这个会在下篇文章中详细讲解。

 

(完)

欢迎大家关注我的公众号 “程序员进阶之路”,里面记录了一个非科班程序员的成长之路

                                                              

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值