Как заменить наследование интерфейсами в шаблоне фабрики? - PullRequest
5 голосов
/ 22 января 2012

Я динамически добавляю и заменяю элементы управления на панели 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
    }
}

1 Ответ

7 голосов
/ 22 января 2012

Вот как вы можете это сделать:

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
    }
}

Вы можете сохранить BaseUserControl, если у вас есть какие-либо общие функции для UserControlA и UserControlB; в противном случае устраните его и сделайте так, чтобы последние два были получены непосредственно из UserControl.

Вы должны определить всех членов, к которым вам может понадобиться доступ из ваших производных классов в интерфейсе IControl. Сюда входят все члены, которые вы унаследуете от UserControl. Однако вам не нужно повторно реализовывать их в ваших конкретных классах.

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

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

Если вам нужно добавить эти элементы управления в приложение Windows Forms - обычно в качестве аргумента вызова метода 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;
    }
}

В вашем коде клиента:

var controlA = ControlFactory.Create("UserControlA").AsWindowsForms();
var controlB = ControlFactory.Create("UserControlB").AsWindowsForms();
panel1.Controls.Add(controlA);
panel1.Controls.Add(controlB);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...