Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a good example for representing the abstract factory pattern

Want to check if this a good example for representing the abstract factory pattern. Here is the theme Dell (Factory) makes xps (Product) Dell (Factory) makes inspiron (Product) hp (Factory) makes envoy (Product) hp (Factory) makes presario (Product)

BestBuy sells computers.

//Abstract factory
abstract class ComputerFactory
{
    public abstract Computer BuildComputer(Computer.ComputerType compType);
}

//Concrete factory
class Dell : ComputerFactory
{
    public override Computer BuildComputer(Computer.ComputerType compType)
    {
        if (compType == Computer.ComputerType.xps)
            return (new xps());
        else if (compType == Computer.ComputerType.inspiron)
            return new inspiron();
        else
            return null;
    }
}

//Concrete factory
class Hp : ComputerFactory
{
    public override Computer BuildComputer(Computer.ComputerType compType)
    {
        if (compType == Computer.ComputerType.envoy)
            return (new envoy());
        else if (compType == Computer.ComputerType.presario)
            return new presario();
        else
            return null;
    }
}

//Abstract product
public abstract class Computer
{
    public abstract string Mhz { get; set; }
    public enum ComputerType
    {
        xps,
        inspiron,
        envoy,
        presario
    }
}

//Concrete product for DELL
public class xps : Computer
{
    string _mhz = string.Empty;

    public override string Mhz
    {
        get
        {
            return _mhz;
        }
        set
        {
            _mhz = value;
        }
    }
}

//Concrete product for DELL
public class inspiron : Computer
{
    string _mhz = string.Empty;

    public override string Mhz
    {
        get
        {
            return _mhz;
        }
        set
        {
            _mhz = value;
        }
    }
}

//Concrete product for HP
public class envoy : Computer
{
    string _mhz = string.Empty;

    public override string Mhz
    {
        get
        {
            return _mhz;
        }
        set
        {
            _mhz = value;
        }
    }
}

//Concrete product for HP
public class presario : Computer
{
    string _mhz = string.Empty;

    public override string Mhz
    {
        get
        {
            return _mhz;
        }
        set
        {
            _mhz = value;
        }
    }
}

public class BestBuy
{
    ComputerFactory compFactory;
    Computer comp;
    public BestBuy(Computer.ComputerType compType)
    {
        if (compType == Computer.ComputerType.xps || compType == Computer.ComputerType.inspiron)
            compFactory = new Dell();
        else
            compFactory = new Hp();

        comp = compFactory.BuildComputer(compType);
    }

    public Computer Sell()
    {
        return comp;
    }
}

Thanks in advance.

like image 579
saidevakumar Avatar asked Feb 24 '11 18:02

saidevakumar


2 Answers

It is a good example of portions of the pattern. The basic construction of objects is a decent example, however, the logic relies upon a single Computer.ComputerType enum. This enum needs to know, in advance, every type of computer exposed by every factory.

Often, the motivation for using an abstract factory is to abstract that type of hard coded requirement out of the picture. Instead of having a single enum, it might be better to add a ComputerType class, and allow the factory to return a collection of available types. You could then use the ComputerType returned to construct the new systems.

This allows you to add other factories without changing your API, which is one of the major advantages of the abstract factory pattern. Read up on the Abstract Factory Pattern - one of the main points is:

The client does not know (or care) which concrete objects it gets from each of these internal factories since it uses only the generic interfaces of their products.

In this case, you're "hard coding" the known types into the enum, which violates this portion of the pattern.

like image 86
Reed Copsey Avatar answered Sep 22 '22 00:09

Reed Copsey


I'm not Factory pattern expert but here are couple of things I would do differently:

  • Instead of an abstract class, I would use an Interface. So if "Dell" needed to inherit from another class it could and still be able to be a ComputerFactory by implementing IComputerFactory for example.
  • The other small thing is use a "switch" instead of an "if/else if" in your BuildComputer function. Who knows how many computers you might end up with in the end.
  • How would you know which concrete Factory to use between Hp and Dell? You might use something like "Autofac" to "resolve" which factory to use.
like image 38
SuperOli Avatar answered Sep 18 '22 00:09

SuperOli