如何用工厂模式中的接口替换继承?

use*_*969 5 c# design-patterns

我在运行时动态添加和替换winform面板中的控件

尽管所有的工作都被告知我实现接口而不是继承baseUserControl.

我全力以赴但我不知道如何使用接口实现相同的结果

我如何编码我的工厂?

如何改进和使用接口呢?

//Simplified noddy example

//Client code
var controlA = ControlFactory
    .Create("UserControlA") as UserControlA;

panel1.Controls.Add(ControlA);

//Factory
public class ControlFactory
{
    public static BaseUserControl Create(string name)
    {
        switch (name)
        {
            case "UserControlA":
                var userControlA = new UserControlA();

                return userControlA;

            case "UserControlB":
                var userControlB = new UserControlB();
                return userControlB;
        }
        return null;
    }
}
   //BaseUserControl
   public partial class BaseUserControl : UserControl
    {
        public BaseUserControl()
        {
            InitializeComponent();
        }

        public virtual void DoSomething()
        {

        }
    }

    public partial class UserControlA : BaseUserControl
    {
        public UserControlA()
        {
            InitializeComponent();
        }

        public override void DoSomething()
        {
            //Do something here
        }
    }

public partial class UserControlB : BaseUserControl
{
    public UserControlB()
    {
        InitializeComponent();
    }

    public override void DoSomething()
    {
        //Do something here
    }
}
Run Code Online (Sandbox Code Playgroud)

Dou*_*las 7

这是你如何做到的:

using System;
using System.Windows.Forms;
using System.ComponentModel;

//Interface
public interface IControl : IComponent
{
    void DoSomething();
}

//Factory
public class ControlFactory
{
    public static IControl Create(string name)
    {
        switch (name)
        {
            case "UserControlA":
                var userControlA = new UserControlA();

                return userControlA;

            case "UserControlB":
                var userControlB = new UserControlB();
                return userControlB;
        }
        return null;
    }
}

//BaseUserControl
public partial class BaseUserControl : UserControl, IControl
{
    public BaseUserControl()
    {
        InitializeComponent();
    }

    public virtual void DoSomething()
    {

    }
}

public partial class UserControlA : BaseUserControl, IControl
{
    public UserControlA()
    {
        InitializeComponent();
    }

    public override void DoSomething()
    {
        //Do something here
    }
}

public partial class UserControlB : BaseUserControl, IControl
{
    public UserControlB()
    {
        InitializeComponent();
    }

    public override void DoSomething()
    {
        //Do something here
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以保留BaseUserControl,如果你有一个是共同的任何功能UserControlAUserControlB; 否则,消除它,并使后两者直接来自UserControl.

应该定义可能需要从IControl界面中的派生类访问的所有成员.这包括您将继承的任何成员UserControl.但是,您不需要在具体类中重新实现这些.

//Interface
public interface IControl : IComponent
{
    void DoSomething();

    // To be inherited from UserControl.
    Size Size { get; set; }
    bool Focus();
    event EventHandler FontChanged;
}
Run Code Online (Sandbox Code Playgroud)

如果需要将这些控件添加到Windows窗体应用程序(通常作为Control.ControlCollection.Add方法调用的参数),则需要获取Control与控件对应的实例.在目前的实施中,这可以通过铸造简单地实现; 但是,如果您决定在将来更改底层实施,则需要与接口的使用者隔离.因此,我会使用:

//Interface
public interface IControl : IComponent
{
    void DoSomething();

    Control AsWindowsForms();
}

//BaseUserControl
public partial class BaseUserControl : UserControl, IControl
{
    public BaseUserControl()
    {
        InitializeComponent();
    }

    public virtual void DoSomething()
    {

    }

    public Control AsWindowsForms()
    {
        return this as Control;
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的客户端代码中:

var controlA = ControlFactory.Create("UserControlA").AsWindowsForms();
var controlB = ControlFactory.Create("UserControlB").AsWindowsForms();
panel1.Controls.Add(controlA);
panel1.Controls.Add(controlB);
Run Code Online (Sandbox Code Playgroud)