Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory Pattern to build many derived classes

I have a factory object ChallengeManager to generate instances of a Challenge object for a game I'm building. There are many challenges. The constructors for each Challenge class derivation are different, however there is a common interface among them, defined in the base class.

When I call manager.CreateChallenge(), it returns an instance of Challenge, which is one of the derived types.

Ideally, I would like to keep the code for the object construction inside the derived class itself, so all the code related to that object is co-located. Example:

class Challenge {}

class ChallengeA : Challenge {
  public static Challenge MakeChallenge() {
    return new ChallengeA();
  }
}

class ChallengeB : Challenge {
  public static Challenge MakeChallenge() {
    return new ChallengeB();
  }
}

Now, my ChallengeManager.CreateChallenge() call only needs to decide the class to call MakeChallenge() on. The implementation of the construction is contained by the class itself.

Using this paradigm, every derived class must define a static MakeChallenge() method. However, since the method is a static one, I am not able to make use of an Interface here, requiring it.

It's not a big deal, since I can easily remember to add the correct method signature to each derived class. However, I am wondering if there is a more elegant design I should consider.

like image 700
gdbj Avatar asked Apr 27 '15 23:04

gdbj


People also ask

What is a Factory Method Pattern good for?

Factory Design Pattern Advantages Factory pattern removes the instantiation of actual implementation classes from client code. Factory pattern makes our code more robust, less coupled and easy to extend. For example, we can easily change PC class implementation because client program is unaware of this.

What is the Factory Method patterns explain with examples?

Factory Method Pattern. A Factory Pattern or Factory Method Pattern says that just define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. In other words, subclasses are responsible to create the instance of the class.

What are the classes in factory design pattern?

The factory design pattern says that define an interface ( A java interface or an abstract class) for creating object and let the subclasses decide which class to instantiate. The factory method in the interface lets a class defers the instantiation to one or more concrete subclasses.

When would you use the GOF Factory Method design pattern?

Factory method lets a class defer instantiation to subclass. Factory needs an object (whose concrete class is not known or whose concrete class may change as per the different application type ) to perform a task.


3 Answers

I really like the pattern you are describing and use it often. The way I like to do it is:

abstract class Challenge 
{
  private Challenge() {} 
  private class ChallengeA : Challenge 
  {
    public ChallengeA() { ... }
  }
  private class ChallengeB : Challenge 
  {
    public ChallengeB() { ... }
  }
  public static Challenge MakeA() 
  {
    return new ChallengeA();
  }
  public static Challenge MakeB() 
  {
    return new ChallengeB();
  }
}

This pattern has many nice properties. No one can make a new Challenge because it is abstract. No one can make a derived class because Challenge's default ctor is private. No one can get at ChallengeA or ChallengeB because they are private. You define the interface to Challenge and that is the only interface that the client needs to understand.

When the client wants an A, they ask Challenge for one, and they get it. They don't need to worry about the fact that behind the scenes, A is implemented by ChallengeA. They just get a Challenge that they can use.

like image 181
Eric Lippert Avatar answered Oct 05 '22 08:10

Eric Lippert


You're "decentralizing" the factory, such that each subclass is responsible for creating itself.

More commonly you would have a central factory that would know about the possible subtypes and how to construct them (often enough, simply by creating a new instance and returning that instance typed as a common interface or common base class). That approach avoids the issue you currently have. I also see no benefit to your current approach. You are currently gaining no encapsulation or code reuse over the more typical implementation of a factory.

For additional reference, have a look at

http://www.oodesign.com/factory-pattern.html

like image 43
Eric J. Avatar answered Oct 05 '22 06:10

Eric J.


Not necessarily the answer you are looking for but... You can use following implementation, if you can move away from static method per class.

using System;

public class Test
{
    public static void Main()
    {
        var c1 = ChallengeManager.CreateChallenge();
        var c2 = ChallengeManager.CreateChallenge();
        //var c = ChallengeManager.CreateChallenge<Challenage>(); // This statement won't compile
    }
}

public class ChallengeManager
{
    public static Challenage CreateChallenge()
    {
        // identify which challenge to instantiate. e.g. Challenage1
        var c = CreateChallenge<Challenage1>();
        return c;
    }

    private static Challenage CreateChallenge<T>() where T: Challenage, new()
    {
        return new T();
    }
}

public abstract class Challenage{}
public class Challenage1: Challenage{}
public class Challenage2: Challenage{}
like image 36
Abhinav Avatar answered Oct 05 '22 06:10

Abhinav