(12)结构型模式——代理

结构型模式——代理(Proxy)

问题背景

当需要监控外界对对象的访问时,考虑使用代理。举个大家都干过的例子哈,在咱这一代小时候,互联网这东西还没这么牛X。你要约女朋友出来,却没有QQ微信电话,只能硬着头皮去她家找。然而开门的不是你女朋友,而是你老丈母娘。老丈母娘问你,叫她宝贝女儿出去干嘛。这时候,要是你说:我们约好要一起写作业,那老丈母娘肯定开开心心地把女儿交给你;但你要是说:我们约好要去开房233……

下面,我们就用面向对象程序模拟以上场景,来介绍代理。

解决方案

首先,在上面的场景中,你扮演的就是“用户”,女朋友是被调用的“真实对象”。但是,对于你一个外部人员来说,系统(女朋友家)不允许你直接访问真实对象,想访问真实对象,必须通过代理(老丈母娘)。于是,我们得到了如下的类图:
程序结构
Date方法是约会,Boy要约Girl,只能调用MotherInLaw的Date方法。传入附加参数,MotherInLaw根据参数决定是否允许Boy访问Girl。同时,MotherInLaw还可以通过“引用计数”来观察自己的女儿在外边搞了多少个男人…这样,对于系统内部来说,就达到了监控访问的目的。

效果

  1. 为真实对象的访问提供了间接性,这种间接性可以实现如安全、日志、延迟加载、引用计数等附加功能。

缺陷

在上面的类图中,我们不难发现,代理模式是面向实现编程而非面向接口编程,这使程序的可扩展性降低。

为了解决这一缺陷,可以再增加两个接口IProxy和IReal分别表示代理和真实对象的抽象。这样一来,就变成了面向接口编程。然而问题又来了,具体的Proxy和具体的Real是绑定的,也就是说每当扩展Real时,就要同时扩展Proxy,这又容易造成类爆炸。

实际上,受限于传统OO的静态性质,纯OO是无法解决类爆炸问题的。在第二期中会介绍混合了反射机制的“动态代理”,这种代理能完美解决类爆炸问题。

相关模式

  1. 适配器:适配器和代理易混淆,适配器的作用是转换接口,代理的作用是监控访问。识别方式就是看目标对象的接口是否发生了变化。
  2. 装饰器:装饰器和代理易混淆,装饰器的作用是动态增强,代理的作用是监控访问。识别方式就是看用户是否能直接访问真实对象。

实现

using System;

namespace Proxy
{
    class Boy
    {
        public interface IGirlFamily
        {
            void Date(params object[] parameters);
        }

        public class Girl : IGirlFamily
        {
            public void Date(params object[] parameters)
            {
                Console.WriteLine("你和女朋友开心地玩了一天");
            }
        }

        public class MotherInLaw : IGirlFamily
        {
            private Girl girl = new Girl();
            public void Date(params object[] parameters)
            {
                if (parameters[0] as string == "我们约好要一起写作业")
                {
                    Console.WriteLine("你:我们约好要一起写作业");
                    Console.WriteLine("老丈母娘:好孩子,去吧");
                    girl.Date();
                } else if (parameters[0] as string == "我们约好要去开房")
                {
                    Console.WriteLine("你:我们约好要去开房");
                    Console.WriteLine("老丈母娘:滚出去!");
                }
            }
        }

        static void Main(string[] args)
        {
            var mother = new MotherInLaw();

            Console.WriteLine("场景一:你来到女朋友家...");
            Console.WriteLine("老丈母娘:你们要去做什么?");
            mother.Date("我们约好要一起写作业");

            Console.WriteLine();

            Console.WriteLine("场景二:你来到女朋友家...");
            Console.WriteLine("老丈母娘:你们要去做什么?");
            mother.Date("我们约好要去开房");
        }
    }
}

运行结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值