装饰有几个界面

Tot*_*oto 6 c# design-patterns

我一直在努力装饰+接口。说我有以下“行为”界面:

interface IFlyable { void Fly();}
interface ISwimmable { void Swim();}
Run Code Online (Sandbox Code Playgroud)

主界面

interface IMainComponent { void DoSomethingA(); void DoSomethingB();}
Run Code Online (Sandbox Code Playgroud)

主界面上的装饰器

    public class Decorator : IMainComponent
    {
        private readonly IMainComponent decorated;
        [..]

        public virtual void DoSomethingA()
        {
            decorated.DoSomethingA();
        }

        public virtual void DoSomethingB()
        {
            decorated.DoSomethingB();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是如何将装饰对象实现的所有接口转发给装饰器。一个解决方案是使装饰器实现接口:

    public class Decorator : IMainComponent, IFlyable, ISwimmable
    {
        [..]

        public virtual void Fly()
        {
            ((IFlyable)decorated).Fly();
        }

        public virtual void Swim()
        {
            ((ISwimmable)decorated).Swim();
        }
Run Code Online (Sandbox Code Playgroud)

但我不喜欢它,因为:

  1. 情况并非如此(“运行时广播异常”),看起来像“装饰器”实现了一个接口。
  2. 这是不可扩展的,我需要添加每个新接口(不要忘记此添加)

另一种解决方案是添加“手动投射”以传播装饰树:

    public class Decorator : IMainComponent
    {
        public T GetAs<T>()
            where T : class
        {
            //1. Am I a T ?
            if (this is T)
            {
                return (T)this;
            }

            //2. Maybe am I a Decorator and thus I can try to resolve to be a T
            if (decorated is Decorator)
            {
                return ((Decorator)decorated).GetAs<T>();
            }

            //3. Last chance
            return this.decorated as T;
        }
Run Code Online (Sandbox Code Playgroud)

但是问题是:

  1. 调用GetAs()后,调用方可以操纵包装的对象。
  2. 如果在调用GetAs之后使用IMainComponent中的方法(可能会导致混乱/不必要的行为)(类似((IMainComponent)GetAs())。DoSomethingB(); ==>这可能会调用包装对象的实现,而不是包装对象的实现)全面装修。
  3. 需要调用GetAs()方法,并且退出带有强制转换/常规“ As”的代码将不起作用。

您如何解决/解决此问题?有解决此问题的模式吗?

PD:我的问题是最终的C#实现,但是解决方案可能更广泛。

Com*_*ubh 0

装饰器模式并不是为了向装饰对象添加新方法。这就是您想要做的事情,而用静态类型语言不可能优雅地做到这一点。

装饰器的有用之处在于装饰器和被装饰组件的接口相同,并且装饰器在沿着装饰器链传递请求之前或之后向方法添加一些额外的功能。