Reputation: 51
I have abstract class-factory Factory
with factory-method getProduct()
and his child classes.
I have abstract class-product Product
and his child classes.
Classes-factories created objects of classes-products.
abstract class Factory {
abstract function getProduct();
}
class FirstFactory extends Factory {
public function getProduct() {
return new FirstProduct();
}
}
abstract class Product {
};
class FirstProduct extends Product {
}
In result I can use this client code:
$factory = new FirstFactory();
$firstProduct = $factory->getProduct();
$factory = new SecondFactory();
$secondProduct = $factory->getProduct();
Question: what for this pattern is necessary? Because in client code I just can use direct classes:
$firstProduct = new FirstProduct();
$secondProduct = new SecondProduct();
Upvotes: 0
Views: 387
Reputation: 394
It's important to note that the Factory Pattern is not always the best solution and for simple case, it is even better having simple new
. For instance, your example would probably be better without Factory.
Factory Pattern takes all its power when you don't need to work on the exact implementation of a class but stay at the 'abstraction layer' (ex. Interface and abstract classes). You can have a look at the "Dependency Inversion Principle DIP" (Depend upon abstraction. Do not depend upon concrete classes).
For instance, let's say you have a software that use Database system. For whatever reason, you know the concrete database used (MongoDB, SQL...) may change later. (Or even just need a fake hard coded database in files during the development). The factory pattern allows you to switch from one to another in just one line, by calling the right Factory, since all the implementation depends upon abstraction. (This is actually the DAO pattern that makes a great use of Factory Pattern, see the oracle documentation for more informations: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html)
Here a concrete and simple example of implementation.
You want to instantiate both players but the concrete player class should be implemented in the more generic way, so that it can be reused later. This is also really important in case of adding several new faction, you don't want to spend time going back to your player class.
To build and run it, copy in Main.java, then javac Main.java
and java Main
The result should be
// Factories ----------------------------------------
abstract class AbsUnitFactory {
public abstract Warrior creaWarrior();
public abstract Peon creaPeon();
}
class OrcFactory extends AbsUnitFactory {
public Warrior creaWarrior() {
return new OrcWarrior();
}
public Peon creaPeon() {
return new OrcPeon();
}
}
class HumanFactory extends AbsUnitFactory {
public Warrior creaWarrior() {
return new HumanWarrior();
}
public Peon creaPeon() {
return new HumanPeon();
}
}
abstract class Unit {
public abstract String getRole();
public abstract String getFaction();
@Override
public String toString() {
String str = new String();
str += "[UNIT]\n";
str += " Role: " + this.getRole() + "\n";
str += " Faction: " + this.getFaction() + "\n";
return str;
}
}
// Warrior Units ----------------------------------------
abstract class Warrior extends Unit {
@Override
public String getRole() {
return "I'm a badass Warrior with the biggest sword!";
}
}
class OrcWarrior extends Warrior {
@Override
public String getFaction() {
return "Orc";
}
}
class HumanWarrior extends Warrior {
@Override
public String getFaction() {
return "Human";
}
}
// Peon Units ----------------------------------------
abstract class Peon extends Unit {
@Override
public String getRole() {
return "I'm a little simple peon... Ready to work.";
}
}
class HumanPeon extends Peon {
@Override
public String getFaction() {
return "Human";
}
}
class OrcPeon extends Peon {
@Override
public String getFaction() {
return "Orc";
}
}
// Main components ----------------------------------------
class Player {
private AbsUnitFactory factory;
private Peon myPeon;
private Warrior myWarrior;
public Player(AbsUnitFactory pFactory) {
this.factory = pFactory;
this.myPeon = this.factory.creaPeon();
this.myWarrior = this.factory.creaWarrior();
}
@Override
public String toString() {
return this.myPeon.toString() + this.myWarrior.toString();
}
}
class Main {
public static void main(String[] args) {
AbsUnitFactory humanFactory = new HumanFactory();
AbsUnitFactory orcFactory = new OrcFactory();
Player humanPlayer = new Player(humanFactory);
Player orcPlayer = new Player(orcFactory);
System.out.println("***** Human player *****");
System.out.println(humanPlayer.toString());
System.out.println("***** Orce player *****");
System.out.println(orcPlayer.toString());
}
}
See how the player class can be reused for any faction and the only line that defines witch faction to use is the Factory. (You may even add a singleton).
These are books I really appreciate (About Design Patterns)
Upvotes: 1
Reputation: 1155
a Factory can be injected instead of the actual class. Suppose you have a class that can be instantiated only at runtime based on some specific conditions, in this case you cannot do new Foo(...args) . One option is to inject FooFactory instead and have it create the Foo instance for you.
Upvotes: 0
Reputation: 15334
If you know at compile time that firstProduct
is always of type FirstProduct
and secondProduct
is always of type SecondProduct
then there is no need for an factory method.
A factory method is only useful if you want to create a product that might be FirstProduct
or might be SecondProduct
depending on the runtime type of a factory. Perhaps, for example, the type of the factory is decided by user input.
Upvotes: 1