Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can replace inheritance with interfaces in factory pattern?

I am dynamically adding and replacing controls in a winform panel at runtime

Even though all works I have been told to implement interfaces rather than inheriting from a baseUserControl.

I am all for it but I dont see how I can I achieve the same result using interfaces

How would I code my Factory?

How can this be improved and use interfaces instead ?

//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
    }
}
like image 558
user9969 Avatar asked Jan 22 '12 15:01

user9969


1 Answers

Here’s how you can do it:

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

You can retain BaseUserControl if you have any functionality that is common to UserControlA and UserControlB; otherwise, eliminate it and make the latter two derive directly from UserControl.

You should define all members you might need to access from your derived classes within your IControl interface. This includes any members you will inherit from UserControl. However, you will not need to re-implement these within your concrete classes.

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

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

If you need to add these controls to a Windows Forms application – typically as the argument to a Control.ControlCollection.Add method call – you will need to get a Control instance corresponding to your control. Under the current implementation, this may be achieved simply through casting; however, this needs to be insulated from the consumers of your interface, in case you decide to change the underlying implementation in the future. Thus, I would use:

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

In your client code:

var controlA = ControlFactory.Create("UserControlA").AsWindowsForms();
var controlB = ControlFactory.Create("UserControlB").AsWindowsForms();
panel1.Controls.Add(controlA);
panel1.Controls.Add(controlB);
like image 162
Douglas Avatar answered Nov 06 '22 06:11

Douglas