Role of Creator in Factory Pattern
Asked Answered
T

4

3

I couldn't understand the role of defining an abstract class / interface for the factory class, which is something i always see in all tutorials on the web. Can somebody please put some light on the importance of CreatorInterface ? Reference UML Diagram of the Factory Pattern

To put in code form, here's what i have :

Code Example 1

// Product
public abstract class Vehicle
{
     public string VehicleType { get; set; }
}

// Concrete Product
public class Bike : Vehicle
{
    public Bike()
    {
        VehicleType = "Two Wheeler";
    }
}

// Concrete Product
public class Car : Vehicle
{
    public Car()
    {
        VehicleType = "Four Wheeler";
    }
}

// Concrete Factory
public class VehicleFactory
{
     public Vehicle GetVehicle(string VehicleType)
    {
        if (VehicleType == "Bike")
            return new Bike();
        else if (VehicleType == "Car")
            return new Car();
        else
            return null;
    }
}

// Client class
public class ClientClass
{
    public void Main()
    {
        VehicleFactory VehicleFactoryObj = new VehicleFactory();
        Vehicle BikeObj = VehicleFactoryObj.GetVehicle("Bike");
        Vehicle CarObj = VehicleFactoryObj.GetVehicle("Car");
    }
}

The above code doesn't contain any abstract class for the 'VehicleFactory' class. But it works fine. Now, what can be the reasons for adding an abstract class for the 'VehicleFactory' ? In my view adding an abstract class will make sense for the Abstract Factory method. [Please correct me if i'm wrong]

Update : Adding my understanding of the Factory Pattern so far.

Definition by GoF :

Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.

As far as i could understand, the core problem statement behind the pattern is that you want to create instances of different classes, without exposing the creation logic to the consumer. Please let me know if i'm getting anything wrong here. I am a little confused here too, because of the examples i see on the web. For e.g on Wiki, the Php and C# examples. I could digest the requirement of the pattern in C# example, but not in PHP example. Anyways, below statements will help you to understand my question clearly.

For instance, we have two vehicle classes Bike and Car in our library, and both of them has vehicle model number. The Bike model number starts with "BK" and car model numbers start with "CR". Now, we wish to return instance of either of the classes depending of the Vehicle Model Number, without exposing the logic to the client. [Note This is an updated scenario, i am putting up since the earlier one had a weak logic of deciding the class, and created confusion over the use of string]

So we can create a vehicle factory class, which exposes a static method that returns the appropriate vehicle instance.

If selection logic is to be known to the client, then i might not have needed the pattern itself. So, the could would look like :

Code Example 2

// Product
public abstract class Vehicle
{
     public int NumberOfWheels { get; set; }
}

// Concrete Product
public class Bike : Vehicle
{
    public Bike()
    {
        NumberOfWheels = 2;
    }
}

// Concrete Product
public class Car : Vehicle
{
    public Car()
    {
        NumberOfWheels = 4;
    }
}

// Client class
public class ClientClass
{
    public void Main()
    {
        String ModelNumber = "BK-125";

        Vehicle CurrentVehicle;
        if (ModelNumber.Contains("BK"))
        {
            CurrentVehicle = new Bike();
        }
        else if(ModelNumber.Contains("CR"))
        {
            CurrentVehicle = new Car();
        }
    }
}

The Factory Pattern let's me simply hide the creational logic from the client by creating a factory. Thus the Client now just needs to call the Factory's create method, and he'll get the appropriate class instance in return. Now the code will look like.

Code Example 3

// Product
public abstract class Vehicle
{
     public int NumberOfWheels { get; set; }
}

// Concrete Product
public class Bike : Vehicle
{
    public Bike()
    {
        NumberOfWheels = 2;
    }
}

// Concrete Product
public class Car : Vehicle
{
    public Car()
    {
        NumberOfWheels = 4;
    }
}

// Concrete Factory
public class VehicleFactory
{
     public Vehicle GetVehicle(string ModelNumber)
    {
        if (ModelNumber.Contains("BK"))
            return new Bike();
        else if (ModelNumber.Contains("CR"))
            return new Car();
        else
            return null;
    }
}

// Client class
public class ClientClass
{
    public void Main()
    {
        VehicleFactory VehicleFactoryObj = new VehicleFactory();
        Vehicle BikeObj = VehicleFactoryObj.GetVehicle("BK-125");
        Vehicle CarObj = VehicleFactoryObj.GetVehicle("CR-394");
    }
}

Now the question comes about the abstract factory class
One benefit of adding an abstract factory class, which i understood from the discussion is that the Client will then be able to override the 'GetVehicle' method to override the logic. For a case where he might have created more vehicle classes for example a 'Truck'. But even in this case, if he want's to override the factory method for all three namely Bike, Car and Truck, he will not be have the entire logic with him as the logic for Bike and Car creation is written in Factory method. Although he will be able to create a new logic for all his new vehicle types. Can someone please put some light on this ?

I more point i want to make here is that This question is regarding the Factory Pattern, i do understand that Abstract Factory pattern will require an Abstract Factory, since in Abstract Factory pattern we're creating Factory of Factories. But in Factory pattern we just have a factory of objects, then why do we need an interface for a factory ?

Thanks in advance !! :-)

Tricuspid answered 26/9, 2017 at 18:32 Comment(1)
btw standard syntax is to have method parameters lowercase. This leads to less confusion in general. So it should be public Vehicle GetVehicle(string vehicleType).Cedar
T
0

@Yair Halberstadt "...Why should i prefer the Factory method over the Static Factory ...". Both serve different purpose. Static factory is a code block which (just) collects the instantiation code for an object hierarchy (it is easy to get convinced about the name). But its nature is static (though can be written at instance level) meaning it gets bound at compile time. off course we can extend static factory but mainly as a patch code. (mostly not preferred at framework level for clients to extend.)

In contrast Factory method is useful for writing common business logic without specifying the concrete beneficiary types which clients will write on later dates.

A fictitious example (with assumption of universal Tax computation)-

public abstract class TaxComputer {
    protected abstract Calculator getCalculator();// Factory method
    public void registerIncome(){
        //...
    }
    public Amount computeTax(){
        Calculator alculator = getCalculator();
        //... Tax computation logic using abstract Calculator
        // Note: Real Calculator logic has not been written yet
        return tax;
    }
}

public interface Calculator {
    Amount add(Amount a, Amount b);
    Amount subtract(Amount a, Amount b);
    Amount multiply(Amount a, double b);
    Amount roundoff(int nearestAmount);
    // ...
}

My all Tax rule implementations are referring to abstract Calculator for operations using Amount. It requires only abstract Calculator at this time. Once the Tax computer is ready, It can be published for clients to extend (With extension point at abstract classes and hook factory method).

Specific client can extend it to computations for Yen (Does not have decimal point) or Dollar/ Pound etc or even calculators which round off (e.g. to next 10 Rupees) after every operation as per local rule.

Same way USDollarTaxCalculator will extend it with their own rules for operations (but can not and need not redefine Tax rules)

public class YenTaxComputer extends TaxComputer {
    @Override
    protected Calculator getCalculator() {
        return new YenCalculator();
    }
}

public class YenCalculator implements Calculator {
    @Override
    public Amount add(Amount a, Amount b) {
        /*Yen specific additions and rounding off*/ 
    }
    @Override
    public Amount subtract(Amount a, Amount b) {/*...*/ }
    @Override
    public Amount multiply(Amount a, double b) {/*...*/ }
    @Override
    public Amount roundoff(int nearestAmount) {/*...*/  }
}

In factory method point is not about hiding creation logic but keeping extensions possible for clients.

The client will look something like

    public class TaxClient {
        public static void main(String[] args) {
            TaxComputer computer = new YenTaxComputer();//
            computeTax(computer);
        }
        /** A PLACE HOLDER METHOD FOR DEMO
         */
        private static void computeTax(TaxComputer computer) {
            Amount tax = computer.computeTax();
            Amount Payment = ...
            //...
        }
    }

Points to be noted here

  1. Clients do not use factory method getCalculator()
  2. Concrete Instance of Creator/ factory can be created by static factories/ reflection etc. choice can be made from system variables, platform, locale etc.
  3. This design pattern comes with its own drawbacks/ costs like parallel class hierarchies (YenTaxComputer has only responsibility of creating instance). nothing comes free.
Teepee answered 29/9, 2017 at 1:19 Comment(2)
Thanks for the example, i found it helpful. A client implementation would have been more helpful. +1 for "In factory method point is not about hiding creation logic but keeping extensions possible for clients."Tricuspid
@PraveenRai - Updated my answer to incorporate client codeTeepee
C
1

Yes it works, but it's not ideal. VehicleFactory has a very general method, and will be a pain in the neck to use once you add more vehicles, as you'll need an extremely long method to check for all the strings.

Imagine you had Fifteen vehicles. Then you'd need an extremely long method to enumerate through all the options and generate the right car. This is both unnecessarily slow, and will be prone to error as you could easily miss something out/delete it, and it will be very hard to debug. In general long methods are bad code smell.

Besides this necessitates that you edit the VehicleFactory class every time you add something that inherits Vehicle. But what happens if a user of your library doesn't have access to it but wants to inherit from vehicle? However by defining an abstract VehicleFactory class he can inherit from that and define his own factory method.

In short the abstract factory method simply makes your code far easier to scale.

Also generating a vehicle dependent on a string is a very bad idea; what if you use an uppercase, or misspell? Besides for which it's quite slow. Better to have something like this.

public abstract class VehicleFactory
{
     public abstract Vehicle GetVehicle(string VehicleType)
}

public class CarFactory : VehicleFactory
{
    public override Vehicle GetVehicle(string VehicleType)
    {
          return new Car();
    }
}

public class BikeFactory : VehicleFactory
{
    public override Vehicle GetVehicle(string VehicleType)
    {
          return new Bike();
    }
}

public class ClientClass
{
    public void Main()
    {
        //Create Factories
        BikeFactory BikeFactoryObj = new BikeFactory();
        CarFactory CarFactoryObj = new CarFactory();

        //create Vehicles from factories. If wanted they can be casted to the inherited type.
        Vehicle VehicleObj=BikeFactoryObj.GetNewVehicle();
        Bike BikeObj = (Bike)BikeFactoryObj.GetVehicle();
        Car CarObj = (Car)CarFactoryObj.GetVehicle();

        //They are all inherited from Vehicle so can be used in a list of Vehicles
        List<Vehicle> Vehicles=new List<Vehicle>()
        {
             VehicleObj,
             BikeObj,
             CarObj
        }
    }
}

There's far less opportunity here for error, and this can be easily scaled by any user of the class.

Cedar answered 26/9, 2017 at 18:39 Comment(10)
I do accept that i should have added an enumeration, instead of passing string for the VehicleType. But, i couldn't understand your statement "VehicleFactory has a very general method, and will be a pain in the neck to use once you add more vehicles, as you'll need an extremely long method". Can you please elaborate a little ?Tricuspid
The problem with your approach is that even when using an Enum as you propose, for every new case you want to handle in the future, you will need to change the source code of the general class (the factory), which you might not have in some real life scenarios. The idea with the abstract/concrete differentiation is to allow an interface to be defined in one place (the abstract part) that consumers can interact with, knowing what to expect and then as many different versions of it (concrete parts) as you need in other parts (even separate assemblies if needed).Analemma
Okay, so one reason which i could understand from discussion is that by creating an abstract class for the factory, you can let the consumer override the 'GetVehicle' function. But, will that be a good practice ? The consumer might mess up with the logic. Secondly, i'm still not clear how creating an abstract class can help in shortening the length of the general method. Let's say that we have fifteen vehicles. I agree that now the 'GetVehicle' method will be long. But how does adding an abstract class for the factory will help to shorten this method ?Tricuspid
@PraveenRai. 1) Yes. He will not be able to mess up any of your logic, just create logic for his own class which he wrote himself. But he can't get rid of your code, or effect any of the other vehicle classes.2)By having an abstract factory, you don't need any code in the abstract class, and instead each vehicle has it's own factory with its own short factory method. So instead of having one gargantuan method in the VehicleFactory class which is impossible to read or debug, you have 15 separate, unconnected methods in each of 15 different classes-one in BikeFactory, one in CarFactoryetc.Cedar
@YairHalberstadt regarding the 2nd Point of your's. If we define individual factory classes, then where will the logic to select the appropriate factory will go ? If possible can you please edit your answer to include an implementation for two vehicle types, e.g. car and bike ? It would be even more helpful, if you can just edit my code itself.Tricuspid
@Praveen will try to do so tomorrow.Cedar
I have recently answered similar question here [link]#46384858Teepee
@YairHalberstadt As far as to my understanding of the pattern goes, the main benefit was hiding away the logic of creation from the client. So, looking at the code example that you've shared, i really couldn't understand what will be consequences of writing the code the way i've written in Example 2 of my edited question. Can you please check that ?Tricuspid
@KedarTokekar That's exactly my question. Why should i prefer the Factory method over the Static Factory method, as described in your answer. Can you please elaborate your point for Factory Method in contrast to the Static Method ?Tricuspid
@PraveenRai The use case you described in your edited question is not a good example of a case where you would use an abstract factory class. By its very definition your example cannot be scaled by the user as the logic is not known to the client.Cedar
M
0

Simply speaking, your base classes should be abstract or not depending on whether you want to be able to declare a New one.

If you want to prevent the a developer (or yourself) from ever going:

var myVehicle = new Vehicle();

And instead enforce that all Vehicles should be the child ones that inherit from Vehicle, then you declare it abstract.

Then when they try and do the above code they get a compilation error that they cannot declare a new abstract class.

There is nothing wrong having the base class non abstract if you are fine with users being able to declare new ones.

Microorganism answered 28/9, 2017 at 4:59 Comment(0)
T
0

@Yair Halberstadt "...Why should i prefer the Factory method over the Static Factory ...". Both serve different purpose. Static factory is a code block which (just) collects the instantiation code for an object hierarchy (it is easy to get convinced about the name). But its nature is static (though can be written at instance level) meaning it gets bound at compile time. off course we can extend static factory but mainly as a patch code. (mostly not preferred at framework level for clients to extend.)

In contrast Factory method is useful for writing common business logic without specifying the concrete beneficiary types which clients will write on later dates.

A fictitious example (with assumption of universal Tax computation)-

public abstract class TaxComputer {
    protected abstract Calculator getCalculator();// Factory method
    public void registerIncome(){
        //...
    }
    public Amount computeTax(){
        Calculator alculator = getCalculator();
        //... Tax computation logic using abstract Calculator
        // Note: Real Calculator logic has not been written yet
        return tax;
    }
}

public interface Calculator {
    Amount add(Amount a, Amount b);
    Amount subtract(Amount a, Amount b);
    Amount multiply(Amount a, double b);
    Amount roundoff(int nearestAmount);
    // ...
}

My all Tax rule implementations are referring to abstract Calculator for operations using Amount. It requires only abstract Calculator at this time. Once the Tax computer is ready, It can be published for clients to extend (With extension point at abstract classes and hook factory method).

Specific client can extend it to computations for Yen (Does not have decimal point) or Dollar/ Pound etc or even calculators which round off (e.g. to next 10 Rupees) after every operation as per local rule.

Same way USDollarTaxCalculator will extend it with their own rules for operations (but can not and need not redefine Tax rules)

public class YenTaxComputer extends TaxComputer {
    @Override
    protected Calculator getCalculator() {
        return new YenCalculator();
    }
}

public class YenCalculator implements Calculator {
    @Override
    public Amount add(Amount a, Amount b) {
        /*Yen specific additions and rounding off*/ 
    }
    @Override
    public Amount subtract(Amount a, Amount b) {/*...*/ }
    @Override
    public Amount multiply(Amount a, double b) {/*...*/ }
    @Override
    public Amount roundoff(int nearestAmount) {/*...*/  }
}

In factory method point is not about hiding creation logic but keeping extensions possible for clients.

The client will look something like

    public class TaxClient {
        public static void main(String[] args) {
            TaxComputer computer = new YenTaxComputer();//
            computeTax(computer);
        }
        /** A PLACE HOLDER METHOD FOR DEMO
         */
        private static void computeTax(TaxComputer computer) {
            Amount tax = computer.computeTax();
            Amount Payment = ...
            //...
        }
    }

Points to be noted here

  1. Clients do not use factory method getCalculator()
  2. Concrete Instance of Creator/ factory can be created by static factories/ reflection etc. choice can be made from system variables, platform, locale etc.
  3. This design pattern comes with its own drawbacks/ costs like parallel class hierarchies (YenTaxComputer has only responsibility of creating instance). nothing comes free.
Teepee answered 29/9, 2017 at 1:19 Comment(2)
Thanks for the example, i found it helpful. A client implementation would have been more helpful. +1 for "In factory method point is not about hiding creation logic but keeping extensions possible for clients."Tricuspid
@PraveenRai - Updated my answer to incorporate client codeTeepee
T
0

I found the following link very helpful to understand the logic behind having an abstract class for Factory, and the logic of using Factory Pattern itself.

https://msdn.microsoft.com/en-us/library/ee817667.aspx

Let me quote the logic behind the pattern from the article

Consider an application that models the assembly of a variety of personal computers. The application contains a ComputerAssembler class that is responsible for the assembly of the computer, a Computer class that models the computer being built, and a ComputerFactory class that creates instances of the Computer class. In using the Factory pattern, the ComputerAssembler class delegates responsibility for creation of Computer instances to the ComputerFactory. This ensures that if the instantiation and/or initialization process changes (e.g. new constructor, use of an activator, custom pooling, etc.), the ComputerAssembler does not need to change at all. This is the benefit of abstracting the creation of an object from its use.

In addition, suppose that the business requirements changed and a new type of computer needs to be assembled. Rather than modifying the ComputerAssembler class directly, the ComputerFactory class can be modified to create instances of a new computer class (assuming that this new class has the same interface as Computer). Furthermore, it is also possible to address this requirement by creating a new factory class (that has the same interface as ComputerFactory) that creates instances of the new computer class (again, with the same interface as Computer). As before, nothing in the ComputerAssembler class needs to change, all the logic just continues to work as it had previously. This is the benefit of abstracting the types of the product and factory into invariant interfaces.

The second paragraph states that the Creator enables us to create new factories, to handle the changes that might have been introduced in the Product, or in the logic of their creation, forcing us to create new factory.

Tricuspid answered 30/9, 2017 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.