静态代理模式(聚合和继承):

静态代理模式:

什么是代理模式? 举个例子吧,就比如超市的产品,超市的产品是由厂家生产,但是我们用户一般不会直接找厂家,二十通过超市去购买产品;
在这里插入图片描述

代理模式也是如此:-

在这里插入图片描述

这个是常见代理模式常见的 UML 示意图:

值得注意的是代理模式的几点:

  1. 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。就像用户不会关心出售的是谁只会关心产品怎样.
  2. 接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。 就像是产品是厂家生产的,而用户是通过超市去购买产品不予用户进行直接接触;
  3. 代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。就像是用户购买东西都选择去超市进行购买,而不会选择厂家购买一样;
  4. 用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作。用户买了产品,实际上是厂家产出的,而超市是作为中间商,它可以是不是做做活动,打打广告来推销产品;

不多说先上代码 (聚合方式):

我以下讲的方式为聚合,这种方式比较灵活,更推荐使用这种方式,这种方式,先产生一个汽车的代理类ProductProxy,让它也去实现Product接口,再将ProductImpl类以成员变量的方式引入,通过构造器赋值,此时就可以在实现的接口方法中调用ProductImpl方法和插入我们要执行的逻辑。

1.先定义一个接口(Product)作为约束

package demo;

/**
 * 定义一个产品接口
 * 这个产品有自己的规格参数作
 *
 * 也就是把这个接口作为一个约束 约定
 *@Author ange
 *@Date 2020/7/8 14:20
 **/

public interface Product {

    /**
     * 产品名称
     * @return
     */
    String getName();

    /**
     * 产品用途
     */
    void getDo();

}

2.定义一个具体的委托类(ProductImpl),它就是即将要被代理的类:

package demo;

import lombok.extern.slf4j.Slf4j;

/**
 * 这是产品的具体实现类,也可以看为工厂产出的具体对象
 *
 *@Author ange
 *@Date 2020/7/8 14:25
 **/
@Slf4j
public class ProductImpl implements Product {

    @Override
    public String getName() {
        return "我是一个产品,我是一个电视!";
    }


    @Override
    public void getDo() {
        log.info("我是电视!我可以播放奥特曼!");
    }

}

3.定义一个代理类(ProductProxy),去代理委托类

package demo;

import lombok.extern.slf4j.Slf4j;

/**
 * 代理类 可以看成是超市,首先超市要去工厂里进货,拿到货以后进行推销,也就是拓展
 *
 *@Author ange
 *@Date 2020/7/8 14:33
 **/
@Slf4j
public class ProductProxy implements Product {

    private Product product;

    public ProductProxy(Product product){
        this.product = product;
    }

    @Override
    public String getName() {
        //我们可以在推销过程中可以进行推销,也就是扩展
        String name = product.getName();
        name += "我是星星品牌的大电视机,全球销量第一!世界最强";
        return name;
    }

    @Override
    public void getDo() {
        product.getDo();
        log.info("我还可以看天气预报!");
        log.info("我还可以看新闻!");
    }
}

看一下效果:

package demo;

import lombok.extern.slf4j.Slf4j;

/**
 *@Author ange
 *@Date 2020/7/8 14:45
 **/
@Slf4j
public class Demo {
    public static void main(String[] args) {
        Product product = new ProductImpl();
        Product proxy = new ProductProxy(product);
        log.info(proxy.getName());
        proxy.getDo();
    }
}

打印结果:

14:46:38.863 [main] INFO demo.Demo - 我是一个产品,我是一个电视!我是星星品牌的大电视机,全球销量第一!世界最强
14:46:38.888 [main] INFO demo.ProductImpl - 我是电视!我可以播放奥特曼!
14:46:38.888 [main] INFO demo.ProductProxy - 我还可以看天气预报!
14:46:38.888 [main] INFO demo.ProductProxy - 我还可以看新闻!

可以看到他的执行过程,首先工厂产出了一个产品也就是 Product product = new ProductImpl(); 接着把这个产品给予超市让它代理出售 Product proxy = new ProductProxy(product); 超市为了提升自己的销量,觉得现在的产品的参数太过平平没有吸引力,所以做了一些广告包装:

@Override
    public String getName() {
        //我们可以在推销过程中可以进行推销,也就是扩展
        String name = product.getName();
        name += "我是星星品牌的大电视机,全球销量第一!世界最强";
        return name;
    }

    @Override
    public void getDo() {
        product.getDo();
        log.info("我还可以看天气预报!");
        log.info("我还可以看新闻!");
    }

静态代理的另一种实现方式 (继承) :

不推荐使用这个使用方式,应为这种方式不够灵活,代码比较臃肿,它只是直接以继承的方式去继承ProductImpl,然后调用父类的方法和参数进行拓展

1.先定义一个接口(Product)作为约束

package demo;

/**
 * 定义一个产品接口
 * 这个产品有自己的规格参数作
 *
 * 也就是把这个接口作为一个约束 约定
 *@Author ange
 *@Date 2020/7/8 14:20
 **/

public interface Product {

    /**
     * 产品名称
     * @return
     */
    String getName();

    /**
     * 产品用途
     */
    void getDo();

}

2.定义一个具体的委托类(ProductImpl),它就是即将要被代理的类:

package demo;

import lombok.extern.slf4j.Slf4j;

/**
 * 这是产品的具体实现类,也可以看为工厂产出的具体对象
 *
 *@Author ange
 *@Date 2020/7/8 14:25
 **/
@Slf4j
public class ProductImpl implements Product {

    @Override
    public String getName() {
        return "我是一个产品,我是一个电视!";
    }


    @Override
    public void getDo() {
        log.info("我是电视!我可以播放奥特曼!");
    }

}

3.定义代理类继承ProductImpl

package demo;

import lombok.extern.slf4j.Slf4j;

/**
 * 继承的方式 代理产品
 *@Author ange
 *@Date 2020/7/8 15:23
 **/
@Slf4j
public class ProductProxyExtend extends ProductImpl {

    public String getName(){
        //我们可以在推销过程中可以进行推销,也就是扩展
        String name = super.getName();
        name += "我是星星品牌的大电视机,全球销量第一!世界最强";
        return name;
    }

    public void getDo() {
        super.getDo();
        log.info("我还可以看天气预报!");
        log.info("我还可以看新闻!");
    }
}

运行一下:

    public static void main(String[] args) {
        Product product = new ProductImpl();
        Product proxy = new ProductProxy(product);
        log.info(proxy.getName());
        proxy.getDo();

        log.info("------------");

        Product extend = new ProductProxyExtend();
        log.info(extend.getName());
        extend.getDo();
    }

打印结果

15:27:38.992 [main] INFO demo.Demo - 我是一个产品,我是一个电视!我是星星品牌的大电视机,全球销量第一!世界最强
15:27:38.995 [main] INFO demo.ProductImpl - 我是电视!我可以播放奥特曼!
15:27:38.995 [main] INFO demo.ProductProxy - 我还可以看天气预报!
15:27:38.995 [main] INFO demo.ProductProxy - 我还可以看新闻!
15:27:38.995 [main] INFO demo.Demo - ------------
15:27:38.995 [main] INFO demo.Demo - 我是一个产品,我是一个电视!我是星星品牌的大电视机,全球销量第一!世界最强
15:27:38.995 [main] INFO demo.ProductImpl - 我是电视!我可以播放奥特曼!
15:27:38.995 [main] INFO demo.ProductProxyExtend - 我还可以看天气预报!
15:27:38.995 [main] INFO demo.ProductProxyExtend - 我还可以看新闻!

可以看到实现结果是一样的;

静态代理类优缺点
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。

2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值