结构型模式 - 代理模式Proxy

学习而来,代码是自己敲的。也有些自己的理解在里边,有问题希望大家指出。

代理模式的定义与特点

        代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。  

在不改变原有代码的基础上,增加自己的东西。分为静态代理动态代理

动态代理的底层:全是反射。并且动态代理类是动态生成的,并不是我们提前写好。这个目前我技术有限,写不明白,还需要大家帮帮我。
动态代理分为两大类,基于接口的动态代理,基于类的动态代理。 

 代理模式的主要优点:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性

代理模式的主要缺点是:

  • 代理模式会造成系统设计中类的数量增加
  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
  • 增加了系统的复杂度;

那么如何解决以上提到的缺点呢?答案是可以使用动态代理方式

 1. 模式的结构

代理模式的主要角色如下。

  1. 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  2. 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  3. 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

其结构图如图 1 所示。

图1

代码

0.通用代码

namespace DesignPattern.ProxyPattern
{
    /// <summary>
    /// 出租接口
    /// </summary>
    internal interface IRent
    {
        /// <summary>
        /// 出租房子
        /// </summary>
        void Renting();
    }

    /// <summary>
    /// 房东
    /// </summary>
    public class Landlord : IRent
    {
        public void Renting()
        {
            Console.WriteLine("我是房东,要出租房子。我已经把钥匙交给了中介。");
        }
    }
}

1.静态代理相关案例代码:

using DesignPattern.ProxyPattern;
using System;

namespace DesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            StaticProxyHelper();
        }

        #region Pattern - Proxy
        static void ProxyHelper()
        {
            Console.WriteLine("静态代理演示:");
            Console.WriteLine();
            RentStaticProxy proxy = new RentStaticProxy(new Landlord());
            proxy.Renting();

            Console.ReadLine();
        }
        #endregion
    }
}

//======================================================================================

using System;

namespace DesignPattern.ProxyPattern
{
    /// <summary>
    /// 出租的静态代理
    /// </summary>
    public class RentStaticProxy : IRent
    {
        private Landlord landlord;

        public RentStaticProxy(Landlord landlord)
        {
            this.landlord = landlord;
        }

        public void Renting()
        {
            GetRentInfo();
            landlord.Renting();
            SeeHouse();
            SetCntract();
            GetFare();
        }

        public void GetRentInfo()
        {
            Console.WriteLine("中介得到你需要租房。并开始搜寻已代理的房源信息");
        }
        public void SeeHouse()
        {
            Console.WriteLine("中介带你看这个房子");
        }

        public void SetCntract()
        {
            Console.WriteLine("签租赁合同");
        }
        public void GetFare()
        {
            Console.WriteLine("中介收中介费");
        }
    }
}


 2.动态代理相关案例代码:

using DesignPattern.ProxyPattern;
using System;

namespace DesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            DynamicProxyHelper();
        }

        #region Pattern - Proxy
        static void DynamicProxyHelper()
        {
            Console.WriteLine("动态代理演示:");
            Console.WriteLine();

            DynamicProxy<Landlord> dynamicProxy = new DynamicProxy<Landlord>(new Landlord());
            IRent _rent = DynamicProxy<Landlord>.As<IRent>();
            _rent.Renting();
            Console.WriteLine(dynamicProxy.ToString());

            Console.ReadLine();
        }
        #endregion
    }
}

//======================================================================================

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;

namespace DesignPattern.ProxyPattern
{
    public class DynamicProxy<T> : DynamicObject where T : class, new()
    {
        private readonly T subject;
        private Dictionary<string, int> m_methodCallCount = new Dictionary<string, int>();

        public string Info
        {
            get
            {
                var sb = new StringBuilder();
                foreach (var item in m_methodCallCount)
                {
                    sb.AppendLine($"{item.Key} called {item.Value} time(s)");
                }
                return sb.ToString();
            }
        }

        public DynamicProxy(T subject)
        {
            this.subject = subject;
        }

        public static I As<I>() where I : class
        {
            if (!typeof(I).IsInterface)
                throw new ArgumentException("I must be an interface type!");

            //Console.WriteLine(typeof(T));
            DynamicProxy<T> inter = new DynamicProxy<T>(new T());
            return inter.subject as I;
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            try
            {
                Console.WriteLine($"Invoking{subject.GetType().Name}.{binder.Name} with arguments [{string.Join(".", args)}]");

                if (m_methodCallCount.ContainsKey(binder.Name))
                    m_methodCallCount[binder.Name]++;
                else
                    m_methodCallCount.Add(binder.Name, 1);

                result = subject.GetType().GetMethod(binder.Name).Invoke(subject, args);
                return true;
            }
            catch (Exception e)
            {
                result = null;
                return false;
            }
        }
    }
}

  这个动态代理,我是真的整不明白了,学艺不精,还望谅解,日后技术提升上来了接着完善。







希望大家:点赞,留言,关注咯~    
😘😘😘😘

唠家常

小黑的今日分享结束啦,小伙伴们你们get到了么,你们有没有更好的办法呢,可以评论区留言分享,也可以加小黑的QQ:841298494,大家一起进步。

  • 客官,看完get之后记得点赞哟!
  • 小伙伴你还想要别的知识?好的呀,分享给你们😄

今日推荐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青衫磊落长歌行

觉得小黑这篇文章不赖,打赏哟~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值