views:

79

answers:

2

Hi I am new to design pattern and apologize if this question is creating any confusion although i am trying to describe the issue in best possible way.I have implemented sample abstract factory pattern in winforms. Front end contains two check boxes to create the objects. Note: If both the check box are checked, both the objects are created. I am using objs.CreateProduct(Maxima,Ultima) method and passing the boolean values to create the objects. Here I am passing the values of both the properts whether I want to create object for ultima or maxima. Can you suggest any other better way to achieve this ? I don't want to pass the properties for maxima and ultima if I am creating the objects.

 public partial class Form1 : Form
    {
        public bool Maxima
        {
            get;
            set;
        }

        public bool Ultima
        {
            get;
            set;
        }


        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Factory[] obj = new Factory[2];
            obj[0] = new B();
            obj[1] = new C();

            foreach (Factory objs in obj)
            {
                iProduct prod = objs.CreateProduct(Maxima,Ultima);
                if (prod != null)
                {
                    prod.GetDetails();
                }
            }

        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox2.Checked)
                Maxima = true;
                else
                Maxima = false;

            if (checkBox1.Checked)
                Ultima = true;
            else
                Ultima = false;
        }
    }


    abstract class Factory
    {
        public abstract iProduct CreateProduct(bool maxima, bool ultima);
    }

    class B : Factory
    {
        public override iProduct CreateProduct(bool maxima,bool ultima)
        {
            if (ultima)
            {
                return new NissanUltima();
            }
            else return null;
        }
    }

    class C : Factory
    {
        public override iProduct CreateProduct(bool maxima,bool ultima)
        {
            if (maxima)
            {
                return new NissanMaxima();
            }
            else return null;
        }
    }

    interface iProduct
    {
        void GetDetails();
    }

    class NissanUltima:iProduct
    {

        public void GetDetails()
        {
            MessageBox.Show("NissanUltima is created");
        }

    }

    class NissanMaxima:iProduct
    {
        public void GetDetails()
        {
             MessageBox.Show("NissanMaxima is created");
        }
    }
A: 

A factory base class interface should be allow clients to create any kind of descendant instance, based only on the parameters provided to its create method. The whole point is decoupling object creation from knowledge about specific concrete types, in order to allow e.g. dependency injection.

If you want to provide distinct initialization data to various descendant factories, that data should be contained in or provided to the factory class itself (since whatever code is creating and configuring the factories is the only part that should know about the concrete type). So, initialize B with the bool value for Ultima and C with the value of Maxima.

Frankly, you may have edited your example a bit too heavily: I'm not really sure of what you are trying to do. If the WinForms code should be unaware of the concrete types, you're going to need to introduce some kind of decoupling interface between that and your factory creation code in order to pass initialization data.

Pontus Gagge
+1  A: 

I would suggest to redesign that code. Abstract Factory is to create an abstract product say a car in your sample. A specific factory addss a trait of the product. Lets say Nissanfactory and Fordfactory then in each CreateFactory() you may scecify a model of the car you want to create.

 abstract class Factory
{
    public abstract iProduct CreateProduct(int Model);
}

class NissanFactory : Factory
{
    public override iProduct CreateProduct(int Model)
    {
        // say 1  is Maxima
        //say 2   is Untima 
        if (Model ==1)
        {
            return new NissanMaxima();
        }
        if(Model ==2)
        {
            return new NissanUltima();

        }
         return null;
    }
}

class FordFartory : Factory
{
    public override iProduct CreateProduct(int Model)
    {
        if (Model == 1)
        {
            return new GrandTorino();
        }
        if (Model == 2)
        {
            return new Mustang();

        }
        return null;
    }
}

//

 private void button1_Click(object sender, EventArgs e)
    {


         Factory[] obj = new Factory[1];
          obj[0] =new NissanFactory();

        private List<iProduct> products = new List<iProduct>();

        //create maxima if it's chacked
        if (checkBox2.Checked)
           products.Add(obj.CreateProduct(1));

         //create ultima
        if (checkBox1.Checked)
            products.Add(prod = obj.CreateProduct(2));

        //now you can navigate via list of created products
        foreach (IProduct car in products)
        {


                prod.GetDetails();

        }

    }
Arseny
I can understand that but I am trying to create the objects of the classes (only if check box is checked) on button click and that is why I have used for loop and changing the properties on checkchanged. Can you please suggest if this is feasible in your scenario ?
@user359562 see my changes
Arseny
Thanks Arseny for your quick response.
@user359562 you're welcome. hope it will help.
Arseny