views:

390

answers:

5

In abstract factory you declare a type which is responsible for creating objects.

This would prevent requiring switch's like this:

 if( type == ONE ) {
     doOne();
  } else if( type == TWO ) { 
     doTwo();
  } etc.

Or the same:

 switch( type ) {
     case ONE: doOne(); break;
     case TWO: doTwo(); break;
     etc....
  }

Into this:

   MyAbstractFactory factoryInstance = ... ? 

   SomeObject object = factoryInstance.createObject();

   object.doX();

As I understand the AbstractFactory will create the correct object which in turn will execute polymorphically the correct behavior.

Then if you use that object 10-20 or 100 times in your progam, you don't have to repeat the switch every time. You just execute the corresponding method and leave to the polymorphism do the job.

   object.doY();

   object.doZ();

Adding a new type is as easy as create a new concrete factory.

All this is clear to me. But...

Where or how is the concrete factory created ( in general terms ) in the first place?

I have always used one single point ( usually in the main() method or in a Configuration.init() method ) which in turn do have the if/else|switch construct which is unavoidable but at least it is used only once.

However I did this "instinctively" ( or by common sense ) but never read in any of the documents describing the pattern WHERE should it be created.

:)

A: 

There are ways to create the concrete class that don't involve if statements, but in that case there is really nothing wrong with an if statement. Although a lot of ifs is probably the the hardest to read code, in this case the purpose of the ifs is simple - a basic jump table for creating an object - which makes everything else simpler. It is readable and there is no complex logic, so it is acceptable (IMHO).

In terms of alternatives, consider if you need a factory method at all. You may not, you may just create the concrete object where you need it, instead of passing a parameter to a factory, the same logic can be used to determine that a given object implementation should be used. This isn't always appropriate, but sometimes the factory is an abstraction too far, and all you needed was different objects working in a Strategy pattern.

Another alternative to an if statement is a map (Dictionary in C#, I believe) that has a lookup based on the type to either a builder object, or the object itself (if it is immutable) or to an instance of the object that can copy itself.

Another option is to make the type an Enum that has a method that can instantiate the right object.

Yishai
+1  A: 

An Abstract Factory is kind of like a factory for factories. It provides a way to create related objects without knowing their concrete type. You still need to know which "Abstract Factory" to "instantiate" meaning which concrete implementation of an abstract factory to instantiate based on some variable.

For instance lets say you're a car/truck manufacturer, you have items such as CarSeats, CarStereo etc and you also have TruckSeats, TruckStereo, they all implement some interface thats common to all of them say IVehicleItem. At this point you can have 2 factories TruckFactory and CarFactory that both implement an abstract factory, say VehicleFactory. Now you can do something like this.

VehicleFactory carFactory = new CarFactory();
IVehicle car = new Car(carFactory);

VehicleFactory truckFactory = new TruckFactory();
IVehicle truck = new Truck(truckFactory);

As you can see I am instantiating the appropriate factory when I need it. This is the best example I can think of at the moment, but I don't think switch statements or if statements in factory classes are bad at all. I usually use Enum's to figure out which class i need.

Edit to add: I think confusion comes with people misunderstanding what an Abstract Factory is. Maybe that is the case for my "downvote". Abstract Factory Pattern is different from Factory Method Pattern.

Wiki - The abstract factory pattern is a compound pattern incorporating the use of the factory pattern AND the interface pattern.

You mention that not Wiki, or GoF..etc show how to instantiate the concrete class. This is incorrect, if you look through the Wikipedia article for Factory Method Pattern you will see this little snippet

public static ImageReader getImageReader(InputStream is) {    

 int imageType = figureOutImageType(is);

   switch(imageType) {
            case ImageReaderFactory.GIF:
                return new GifReader(is);
            case ImageReaderFactory.JPEG:
                return new JpegReader(is);
            // etc.
        }
}

If you read the Wikipedia article for Abstract Factory Pattern you will see this little snippet of code.

public static GUIFactory createOsSpecificFactory() {
        int sys = readFromConfigFile("OS_TYPE");
        if (sys == 0) {
            return new WinFactory();
        } else {
            return new OSXFactory();
        }
    }

The point is there is no "right" way. You instantiate your concrete classes based on what you are trying to do in the application. Sure "if" or "switch" statements are avoidable. But personally I don't see anything wrong with using them.

Stan R.
Well this is my point. I can't hard code new CarFactory() or can I? This is my question. What's the correct way? Hardcode an implementation and change it upon the distribution? Could that be a possibility? What about those places where it should be dinamically loaded?
OscarRyz
what exactly is the downvote for?
Stan R.
A: 

Since the main advantage of abstract factories is separating the knowledge of which concrete items are being created by the factory from the factorie's client, you would like to keep that knowledge (and, that includes, obviously, the concrete factory implementation) away from the rest of the code. One way to do that is to create a "FactoryService" that provides access to the abstract factory instance, at run time.

Your client code may look like:

FactoryService service = FactoryService.instance();
MyAbstractFactory factory = service.getFactory();
SomeObject obj = factory.createObject();

This way, you hide the logic of instantiating the factory inside the service, and the service can, for example, read the class name from a configuration file.

Many frameworks have component lifecycle management that allow for creating components and setting their dependencies (Spring, as mentioned, is one). If you want to be Spring-based, you can configure Spring to inject a specific instance of a factory into your factory service.

Another advantage of this method is testability: You can configure your test runner to create a mock-factory and inject it into your service. Every user of the service will, without any change to their code, receive this mock-factory used for testing purposes.

Armadillo
The FactoryService is in turn an AbtractFactory it self. And the question repeats? When to instantiate it? The second part is one choice, have a dependency injector read a config file. :)
OscarRyz
Not necessarily - The FactoryService is a concrete implementation (singleton, in the case demonstrated above), that hides the details of creating the concrete instance of the abstract factory.True, the FactoryService is a factory, but not an AbstractFactory.
Armadillo
A: 

I've found that there are two scenarios when I'm using AbstractFactory.

The first is when only one concrete class will be used for a run of an object. The canonical example of this is database access code: you aren't going to be accessing you DB in SQL Server and then suddenly switch to Oracle. The concrete class is stable. For that I use the Provider model: define a ProviderBase class, a ProviderCollection class, etc.

The other scenario is when the concrete class depends on the state of the application. In that case I normally provide a factory method on the abstract base class that returns the appropriate concrete class. Within that method I'll usually just have a switch statement to decide which concrete class to instantiate. I did once try what somebody else suggested and stored a copy of all of the concrete classes in a collection but for that particular application the performance of instantiating all of those classes at that time wasn't acceptable. However both these choices are perfectly valid and fairly easy to implement.

Jeff Hornby
A: 

The use of some IoC framework in this instance is the most flexible solution -- Spring was recommended in earlier answers, Google Guice is another excellent choice, which is very easy to start with.

However, if a pure Java solution is needed enums work really great. Pls consider the following example:

enum FactoryConfig {
  CONFIG_1 {
     IFactory instantiate() {
        return ...
     }
  },
  CONFIG_2 {
     IFactory instantiate() {
        return ...
     }
  },
  CONFIG_3 {
     IFactory instantiate() {
        return ...
     }
  };

  abstract IFactory instantiate();
}
...
// and its usage..

IFactory factory = FactoryConfig.CONFIG_3.instantiate();

More about a similar use of enums can be found for example here and here.

01es
You do not need factories in your case. All you need - create a single factory for your objects. This convrete factory will return classes with interface you need to use everywhere. Objects created by this implementing different realizations of this interface. When you need to create your object you are delegating this to factory, providing everything it need to create one. Factory returns you the concrete object and you are working with it according to the common interface. That`s all, no need to create multiple factories.
Yaroslav Yakovlev