Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

This Is How To Use The Factory Method Pattern in Delphi

This Is How To Use The Factory Method Pattern in Delphi

Photo by Andrea Piacquadio: https://www.pexels.com/photo/engineer-working-with-laptop-at-table-3769135/

Factory Method Pattern in Delphi

Do you want to know what the Factory Method Pattern is and what it can do for you? When you are writing simple or complex applications, you might need to create multiple classes inheriting the same class or implementing the same interface. This is easier when we have a small number of classes at the same level of inheritance. However, even with the best app builder software, when more and more classes are introduced, it becomes more difficult to maintain the hierarchy and to support the creation of objects at many different places.

To solve this problem, the Factory Method Pattern [1] was introduced. 

The Factory Pattern has two types.

  1. The Factory Method Pattern
  2. The Abstract Factory Pattern

In this article, we are going to have a look at the Factory Method design pattern. We will explain what it actually is, what problems it solves, what pros and cons it has, and how we can implement it in Delphi.

What is the Factory Method Pattern?

The Factory Method Pattern solves problems of object creation and maintenance by separating the creation of objects from the concrete implementation of classes. This is done by creating a Factory class that contains methods for instantiate classes that implement the same interface or are inherited from the same class.

Below you can see an easily understandable example with code.

Is there a Delphi example of the Factory Method Pattern?

Ok, let’s show you an example of the Factory Method Pattern.

Bill works as a programmer at an automated bakery that sells cheesecakes. His job is to write code that helps to create the type of cheesecake that a customer chooses. Easy job! Because, currently, there are only two types of cheesecakes that the bakery offers. Strawberry and Blueberry.

Bill started by writing classes for two types of Cheesecakes as you can see below and a function to create an instance of one of these two depending on the input received from the user. Bill wrote this function in the project file to make code easier to write and called it just there.

Unit Name: StrawberryCheeseCake.pas

[crayon-67679e98a935d036023252/]

Unit Name: BlueBerryCheeseCake.pas

[crayon-67679e98a9369909805137/]

Why is the Factory Method Pattern useful?

To illustrate why the Factory Method Pattern is needed, let’s continue with our example.

Imagine Bill needed to write the main function to get input from the user and instantiate one of these classes depending on that input.

The code can be found below.

File Name: CheeseCakeShop.dpr

[crayon-67679e98a936e997809833/]

When Bill compiled and ran his code, he found out that it worked like a charm and he could see an output that varied depending on the input supplied.

Input: Strawberry

 

Input: Blueberry

 Wow! Amazing!

Bill was very happy that his code was working correctly and the bakery where he was working at that moment started gaining popularity. It was growing and more people were recruited to perform specific tasks.

One of such new positions is CCFO – Chief Cheesecake Flavor Officer. This new person’s name is Jake and he looked creative. His responsibility is to create new flavors of Cheesecakes. Sounds interesting! Right?

He is doing his job well from the very first day and created a new flavor of Cheesecake which is “Mango” cheesecake. Beautiful!

One day, Jake came to Bill and asked: “Hey Bill, can you make changes to your code so that we can create this new Mango cheesecake and give it to our customers?”

Bill thought a little bit and said: “Sure. Why not?”

Bill knew exactly what to do.

He went ahead and introduced the following changes to his code

  1. Created a new class called “MangoCheeseCake” similar to the other two classes. 
  2. Added a new flavor called “ckfMango” type to the CheeseCakeFlavour enumeration 
  3. Added a MangoCheeseCake unit to the uses list of the project file and
  4. Introduced changes to the “PrepareCheeseCake()” function to dispatch Mango cheesecake if a customer selects it.

He built his project and found that his code works like a charm and became happy. Starting from the following day, customers at the bakery could get Mango Cheesecake if they chose it on the menu.

Jake was happy but Bill was happier that morning.

As Jake is creative, he couldn’t stop thinking about new flavors and experiments.

Just before the day ended, Jake came to Bill to speak about a new flavor of Cheesecake “Coffee” that he created and asked to change the code so that his new cheesecake could be sold if a customer selects it. Bill agreed but he had a rather sad face because he knew that he would need to perform the same repetitive steps again to make the new flavor available.

Going home, Bill couldn’t stop thinking about all the new flavors that Jake would create in the future and the same repetitive changes that he would need to introduce to that code.

While thinking about it, he also remembered the words of one of his computer programming professors from college.

He used to say: “If you write the same code once, encapsulate it. If you write the same code twice, add another layer of encapsulation. If you write the same code thrice, stop being a programmer.

In a separate article, know more about the brilliance of DNA manipulation in this article about Delphi’s DNABaser.

What problem does the Factory Method pattern solve?

Bill couldn’t stop thinking about all the ways he could avoid this redundant code writing and make his code easier to write, change and maintain.

As he finished his dinner he recollected the Factory Method – Design Pattern that the same professor had explained.

He remembered that the Factory Method – Design Pattern is used to separate creation from implementation and can be a solution to the code redundancy problem.

The next morning, Bill came back to the bakery and took a look at his code. Since he recollected all the programming principles that the professor had explained in the college, he found out that he had a new approach to his code.

Now, just when he looked at his code his eyes captured all the units in the uses list of the project file and he realized that to add any new flavor of Cheesecake he would need to update the list of uses and even make changes to the project file. He thought: “My code is so tightly coupled and I didn’t even think about it for so long. I must do something about it now.”

He also studied detailed steps to implement the Factory Method – Design Pattern and came up with the following steps to implement the same in his Cheesecake project.

  1. First of all, as all Cheesecake flavor classes were similar and had the same set of methods, he decided to create an interface that would have the same set of methods and implement all Cheesecake classes from this interface. This would ensure that new flavor classes have the same set of methods and also simplify implementation.
  2. Then, he needed to create a Factory class that would have all the methods to create objects of all flavor classes
  3. He also had to create a factory Generator class which would create a factory object depending on the input supplied
  4. It was also necessary to create an object of the Factory Generator class in the project file and just call one function.
  5. Done.

Below you can see the code changes that he introduced.

Unit Name: CheeseCakeInterface.pas

[crayon-67679e98a9370996910124/]

E.g. Class TStrawberryCheeseCake

[crayon-67679e98a9379669483387/]

Unit Name: CheeseCakeFactory.pas

[crayon-67679e98a937b114267296/]

Unit Name: CheeseCakeFactoryGenerator.pas

[crayon-67679e98a937c265347692/]

Unit Name: CheeseCakeShop.dpr

[crayon-67679e98a937f889253715/]

Well done! There was a lot of code refactoring.

The code looked a little bit more complicated than before. But Bill felt a fraction of satisfaction after implementing all the coding principles he had learned at the college. However, he was still unsure if this was going to help him.

After all this, Bill remembered a discussion with Jake about the new flavor of cheesecake which would be “Coffee”.

He looked at the code again and started to think about changes he would need to make in the new code structure to implement this new flavor. He came up with the steps that are enumerated below.

  1. To create a new flavor class TCoffeeCheeseCake implementing an interface “ICheeseCake”
  2. To create a new method in CheeseCakeFactory to create and return a Coffee flavor class object
  3. To make changes in the PrepareCheeseCake method to call a new method from CheeseCakeFactory

As soon as he introduced the above-mentioned changes to his code, he realized that adding a new flavor became much easier now and no changes to the project file would be required.

Wow! This is amazing!

 Now, Bill doesn’t about any new flavors Jake will decide to offer.

Bill has become creative too!!

What are the pros of the Factory Method Pattern?

  1. Tight coupling is avoided by separating concrete implementation and creation
  2. The Single Responsibility Principle is followed by moving object creation code to one place, making the code easier to support
  3. Open/Closed Principle: New classes can be easily introduced without breaking existing implementation

What are the cons of the Factory Method Pattern?

  1. The code may become more complicated as you need to introduce many new classes for the implementation

(But as you progress with the introduction of new classes, you will notice that the process of maintaining and changing classes is much easier than it was before.)

How can I try out the Factory Method pattern?

You can download a free copy of RAD Studio with Delphi today and try out the above code – plus a whole lot more! RAD Studio is extremely easy to use and can create applications which can run on Windows, macOS, iOS and Android with a single code base. It has tons of advanced features designed to make you super-productive and creating apps for your colleagues and customers faster than almost any competing technologies thanks to its robust VCL and FMX frameworks and low-code or no code approach to rapid application development.

References

[1] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 107ff. ISBN 0-201-63361-2.


This article was written by Embarcadero Tech Partner Softacom. Softacom specialize in all sorts of software development focused on Delphi. Read more about their services on the Softacom website.

Exit mobile version