【问题标题】:Understanding Proxy Pattern in C#了解 C# 中的代理模式
【发布时间】:2017-03-29 02:13:25
【问题描述】:

假设我试图通过类似这样的其他类来访问一个类的方法

class SuperClass
    {
        public interface ISubject
        {
            void Print();
        }
        private class Subject : ISubject
        {
            public void Print()
            {
                Console.WriteLine("this is a print");
            }
        }
       public class Proxy {
            ISubject subject;
            public void CallOtherMethod() {
                subject = new Subject();
                subject.Print();
            }
        }
    }
    class Client: SuperClass
    {
        static void Main() {
            Proxy proxy = new Proxy();
            proxy.CallOtherMethod();
        }
    } 

这被称为代理类吗?或者它是否需要有一个接口作为参考然后我们必须调用该方法?比如这样的

class SuperClass
    {
        public interface ISubject
        {
            void Print();
        }
        private class Subject : ISubject
        {
            public void Print()
            {
                Console.WriteLine("this is a print");
            }
        }
        public class Proxy : ISubject
        {
            ISubject subject;
            public void Print()
            {
                subject = new Subject();
                subject.Print();
            }
        }
    }
    class Client : SuperClass
    {
        static void Main()
        {
            ISubject proxy = new Proxy();
            proxy.Print();
        }
    }

【问题讨论】:

  • 使用代理模式,您可以将ISubject 的实例传递给proxy.Print() 方法,然后Proxy 可能有额外的保护措施,或其他相关功能要调用,例如通知者。在您的示例中,Proxy 应该被称为 Printer
  • @LordWilmore 那么代理模式和桥接模式有什么区别?在桥接模式中,我们将接口的实例传递给抽象类
  • @LordWilmore 我应该在这个问题中更新我对桥接模式的理解,以便清楚地了解我在说什么吗?

标签: c# proxy-pattern


【解决方案1】:

通常,代理模式的目标是拦截。也就是说,捕获对某种类型的某些(或全部)方法的调用,并在实际调用之前/之后执行一些操作。为此,代理必须从目标类型继承

例如:

public class Subject
{
    public virtual void Print()
    {
        Console.WriteLine("this is a print");
    }
}

public class SubjectProxy : Subject
{
    public override void Print()
    {
        Console.Write("Before calling base.Print()");
        base.Print();
        Console.Write("After calling base.Print()");
    }
}

现在,当您在代码中的某个位置期待 Subject 时,您实际上可能会得到 SubjectProxy 并仍将其视为 Subject

public Subject GetSubject()
{
    return new SubjectProxy();
}

Subject subject = GetSubject();
subject.Print(); // would use the proxied method

(这并不是说实现拦截的唯一方法是通过继承。我认为有代理风格使用组合/装饰的变体来实现)

【讨论】:

  • 那么装饰器模式和代理模式有什么区别呢?装饰器模式也有同样的作用,对吧?
  • @LijinJohn,据我所知。装饰器主要用于扩展对象的功能,而不是拦截其方法。然而(正如我在答案中已经提到的),也有一些方法可以使用装饰来实现这一点。但是,如果你真的想要拦截,Proxy 是最简单的方法。
  • @LijinJohn,另外,在使用装饰器时,目标对象必须知道装饰对象并在自己的代码中显式调用它。 Proxy 保持目标对象不被察觉且大部分未触及,它只需要 virtual 在要代理的方法上。
  • 那么,我的第一个示例代码是代理模式吗?如果不是那么,如果我用 ISubject 重载 CallOtherMethod() 并调用方法 Print 使其成为代理模式...请耐心等待我并解释...谢谢
  • @LijinJohn,有很多与设计模式相关的误解和相互矛盾的信息。老实说,我不认为我可以将某个设计“证明”为“有效代理”或“有效 X”。更好的方法是通过引入这个包装Subject 的额外类来专注于您想要实现的目标,并问自己为什么它在那里。话虽如此,调用subject = new Subject() in 方法本身可能不是一个好的设计,您最好将其注入 到方法中。
猜你喜欢
  • 1970-01-01
  • 2013-07-20
  • 2012-09-06
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 2021-04-27
  • 2011-10-31
相关资源
最近更新 更多