Constructors Use Initialization Lists Or Assignment Abroad

Refactoring Replace Constructor with Factory Method

Problem

You have a complex constructor that does something more than just setting parameter values in object fields.

Solution

Create a factory method and use it to replace constructor calls.

Before

class Employee { Employee(int type) { this.type = type; } //... }

After

class Employee { static Employee create(int type) { employee = new Employee(type); // do some heavy lifting. return employee; } //... }

Before

public class Employee { public Employee(int type) { this.type = type; } //... }

After

public class Employee { public static Employee Create(int type) { employee = new Employee(type); // do some heavy lifting. return employee; } //... }

Before

After

class Employee { ... static function create($type) { $employee = new Employee($type); // do some heavy lifting. return $employee; } ... }

Why Refactor

The most obvious reason for using this refactoring technique is related to Replace Type Code with Subclasses.

You have code in which a object was previously created and the value of the coded type was passed to it. After use of the refactoring method, several subclasses have appeared and from them you need to create objects depending on the value of the coded type. Changing the original constructor to make it return subclass objects is impossible, so instead we create a static factory method that will return objects of the necessary classes, after which it replaces all calls to the original constructor.

Factory methods can be used in other situations as well, when constructors aren't up to the task. They can be important when attempting to Change Value to Reference. They can also be used to set various creation modes that go beyond the number and types of parameters.

Benefits

  • A factory method does not necessarily return an object of the class in which it was called. Often these could be its subclasses, selected based on the arguments given to the method.
  • A factory method can have a better name that describes what and how it returns what it does, for example .
  • A factory method can return an already created object, unlike a constructor, which always creates a new instance.

How to Refactor

  1. Create a factory method. Place a call to the current constructor in it.
  2. Replace all constructor calls with calls to the factory method.
  3. Declare the constructor private.
  4. Investigate the constructor code and try to isolate the code not directly related to constructing an object of the current class, moving such code to the factory method.

Tired of reading?

No wonder, it takes 7 hours to read all of the text we have here.

Try our interactive course on refactoring. It offers a less tedious approach to learning new stuff.

Let's see...

Smart pointers are objects that act like pointers, but automate management of the underlying memory. They are extremely useful for preventing memory leaks, and are essential for writing exception-safe code.

By convention, class names in SNAP start with letter and their corresponding smart pointer types have replaced with .

In the following example, variable is defined as an undirected graph. is the base type and is its corresponding smart pointer type:

PUNGraph Graph = TUNGraph::New();

The following example shows how an undirected graph is loaded from a file:

{ TFIn FIn("input.graph"); PUNGraph Graph2 = TUNGraph::Load(FIn); }

To implement smart pointers for a new class, only a few lines need to be added to the class definition.

The original class definition:

The original class definition after smart pointers are added:

class TUNGraph; typedef TPt<TUNGraph> PUNGraph; class TUNGraph { ... private: TCRef CRef; ... public: ... static PUNGraph New(); // New() method static PUNGraph Load(TSIn& SIn); // Load() method ... friend class TPt<TUNGraph>; };

The new code declares , a smart pointer type for the original class . A few new definitons have been added to : , a reference counter for garbage collection; , a method to create an instance; and a declaration for . The method for a smart pointer class returns a pointer to a new object instance rather than no result, which is the case for regular classes.

An example of definitions for the and methods for are shown here:

static PUNGraph New() { return new TUNGraph(); } static PUNGraph Load(TSIn& SIn) { return PUNGraph(new TUNGraph(SIn)); }

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *