• 设计模式学习心得<代理模式 Proxy>


    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

    在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

    概述


    • 意图
      为其他对象提供一种代理以控制对这个对象的访问。

    • 主要解决
      在直接访问对象时带来的问题。
      比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

    • 何时使用
      想在访问一个类时做一些控制。

    • 如何解决
      增加中间层。

    • 关键代码
      实现与被代理类组合。

    • 应用实例

    1. Windows 里面的快捷方式。
    2. 买火车票不一定在火车站买,也可以去代售点。
    3. 一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。
    4. Spring Aop。
    • 优点
    1. 职责清晰。
    2. 高扩展性。
    3. 智能化。
    • 缺点
    1. 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
    2. 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
    • 使用场景
      按职责来划分,通常有以下使用场景:
    1. 远程代理。
    2. 虚拟代理。
    3. Copy-on-Write 代理。
    4. 保护(Protect or Access)代理。
    5. Cache代理。
    6. 防火墙(Firewall)代理。
    7. 同步化(Synchronization)代理。
    8. 智能引用(Smart Reference)代理。
    • 注意事项
      • 与适配器模式的区别
        适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
      • 与装饰器模式的区别
        装饰器模式为了增强功能,而代理模式是为了加以控制。

    实现


    原有售票服务,现在代理售票点同样提供售票服务,不必跑到机场、长途大巴车站购买票。
    代理售票点,只是简单做了记账。

    • 适配器模式有如下三个角色
      Target:目标接口SellTicketsService
      Product:目标实现产品类SellTicketsServiceImpl
      Proxy:代理实现类ProxySellTicketsServiceImpl

    • step 1:目标接口

    public interface SellTicketsService {
        String sell(String type, BigDecimal amount);
    }
    
    • step 2:目标实现产品类
    public class SellTicketsServiceImpl implements SellTicketsService {
        private Map<String, Integer> ticketCollection = new ConcurrentHashMap<String, Integer>() {{
            put("air", 15);
            put("bus", 35);
        }};
    
        @Override
        public String sell(String type, BigDecimal amount) {
            if (amount.doubleValue() < 0.0D) {
                throw new IllegalArgumentException("amount can not less than zero.");
            }
            Integer count = ticketCollection.get(type);
            if (count == null || count < 0) {
                throw new IllegalStateException("ticket collection is empty");
            }
            count = ticketCollection.computeIfPresent(type, (k,v) ->  v - 1);
            if (count == 0){
                ticketCollection.remove(type);
            }
            return "ok";
        }
    }
    
    • step 3:代理实现类
    public class ProxySellTicketsServiceImpl implements SellTicketsService {
    
        private static final Logger logger = LoggerFactory.getLogger(ProxySellTicketsServiceImpl.class);
        private SellTicketsService service = new SellTicketsServiceImpl();
    
        @Override
        public String sell(String type, BigDecimal amount) {
            logger.info("sell type:{} amount:{}",type,amount);
            return service.sell(type,amount);
        }
    
        public static void main(String[] args) {
            System.out.println(new ProxySellTicketsServiceImpl().sell("bus",BigDecimal.ONE));
        }
    }
    
  • 相关阅读:
    Chrome浏览器网页截全屏算法以及实现
    去除scons构建动态库的前缀lib
    Javascript的继承
    win7 VS2008 ffmpeg release 版本崩溃 0x00905a4d 处未处理的异常
    shell脚本获取随机数random
    iOS navigationbar添加实现
    TableView中改变Button按钮状态
    将TableView的中的Label和Cell行数绑定
    build diff: /../Podfile.lock: No such file or directory
    initramfs-tools ... update-initramfs: Generating /boot/initrd.img-3.14-kali1-amd64 mktemp: failed to create directory via template `/var/tmp/mki
  • 原文地址:https://www.cnblogs.com/snifferhu/p/9191996.html
Copyright © 2020-2023  润新知