Factory-Pattern in ABAP OO
When you work with ABAP Objects you always need to create instances of classes. Even if you use “CREATE OBJECT” to create those instances, you probably faced with the problem, that it is not so comfortable as if you have a function for creating objects in the same way. Or, you have a complex logic to create each instance.
For those cases, there is a design-pattern for creating instances. This pattern is called “Factory”-pattern. There is also a pattern called “factory-method”, which is different, because it combines the creation and relationship of objects. Thanks to Naimesh Patel, who advise me of this point.
The factory-pattern is one of the most used design pattern. It creates object instances without exposing the concrete instantiation logic. The instantiated objects will be accessable through an interface, which encapsulate the concrete implementation to the users.
In the classical GoF-Pattern, the factory-pattern looks like this:
A client needs a product (a.k.a. “class”) and asks a factory for a concrete instance by passing the neccessary parameters to it. The factory creates a class of a specific interface ( “Product” ) and gives the instance back to the client. The specific interface should also be an abstract class, but by using an interface you will have a much better support for the separations-of-concerns principle.
The ABAP-way of the factory pattern
Sure, it should be very simple, to transfer the underlying UML to a ABAP class structure. But, you have much more than just a OO-language: The SAP Netweaver AS gives you some nice featues – customizing with a maintenance dialog is one of them.
So, here is my approach for the ABAP OO-Factory:
As you can see, the factory use informations out of a customizing table and holds all created instances in a internal table. The rest ( Interface, Concrete Classes) are simple ABAP OO Elements. By the way: If you can be sure, that the instances should not be buffered so far, you do not need an internal table with all created instances.
At least, the “create” Method is not so complex:
The customizing table should look like this:
For your internal table in the factory, you should define a DDIC-Structure and Tabletype which includes the customizing information and a reference to the created instance.
One hint: Create a view on SEOCLASSTX and SEOMETAREL with the used interface as constant for “REFCLSNAME”, use it as foreign-key and you get a DDIC-based check, if the used class implements the correct interface.
And last, but not least: you need a maintenance view, created by the maintenance view generator.
Why should you use a factory-pattern?
With the factory pattern you centralize the create of objects within your application. By using this approach, you can manage the instantiation of objects ( “Products” ) and separate the usage of the concrete implementation logic.
Through interfaces you introduce the design principle “separation of concerns” and you give a contract for all users of your classes. By accepting this contract the users of your interface count on the correct implementation of the contract.
Additional, you get an overview about who implements your interface and where is it used – just look in the ABAP Workbench and expand the implementation tree of your interface:
Adding new aspects to your software
Another important thing, which I have not mentioned so far: You can build your factory in a way, that you can very easy introduce proxy-classes (another design pattern) which covers new aspects – for example: logging or authentication – without changing the underlying classes.
By using this, your user does not affect, that there is another implementation – the interface, and its underlying contract is stil fulfilled.
The factory-pattern is an important pattern for creating object instances within your own code. With this pattern, you can get a more manageable, extensible and customizable software.
Nice to see that you are using Design Patterns. I also implement them in my developments and write about them on my blog. Check them out at ABAP Objects Design Patterns.
I have few doubts on your Factory method implementation:
thank you for your useful annotations. Great to read your blog.
For my usage, I do not want to have a direct linking between the Factory and the created object. I prefer the so called "loose coupling" principle to achieve a maximum of flexibility.
And so, you got right: It is not the so called "factory-method"-pattern. I correct this point in my blog.
In the origin purpose of the factory pattern, there will be a object created every time you call the create-method. But I found out, that there are some circumstances, where you need to buffer your instances. E.g. when they are very expensive to create. In my blog I comment this point, that you can do it without the buffering.
I think, that the described factory pattern has a very important feature: You can customize the creation of objects without changing the factory implementation.
I'm glad that you like my blogs.
When we use Singleton and Factory together, we try to get best out of both. Shouldn't it be called as Singleton Factory? What do you think?
this is a problem, I am sometimes faced with, too. In practice, I introduce a method "initialize" in the interface, which adopt the logic of the constructor with all its necessary parameters.
You can build a method which can do this, but that'll be very difficult to implement due to the reasons outlined by you!
Due to the fact, that we create instances of a specific interface, we cannot use a constructor with specific parameters. So, I use an initializer-method.
I think both of us are echoing the same sentiment - FACTORY methods should not be generic!
I am facing a concrete problem trying to refining an existing factory pattern.
In the RE module, i have a class CL_RECN_CONTRACT and a factory class CF_RECN_CONTRACT, with a nice method FIND, returning an instance of contract, given it's key.
Now I have created a custom subclass of CL_RECN_CONTRACT, in order to add some custom logic (just two/three methods) to the standard implementation, and I need a factory method for this new class. But, unfortunately, CF_RECN_CONTRACT is "final", so I can't create a subclassed factory with a refined implementation of FIND method. Do you have any suggestion on how to deal with this pattern?
Thanks in advance,
well, this is the my-called "Final-Class-Of-SAP"-Pattern 😉 I thought about, that the developer of the class-builder just forget to unset this flag...and many examples show that this not just a assumption...
I do not know the classes and do not have any access to them at the moment. Have you look into the FIND-method, if the class-name is build dynamically in there? If so, try to come into this processing with your class - for example by entering your class in a special customizing-table. If the classname is hardcoded ( and I do not wish it to you ), you still have the option to enhance the find-method with an implicit enhancement.
If you have to enhance the FIND-Method it should be possbile, that you will have to copy the whole method-coding into the enhancement section and then add your specific coding. Obviously this is not a very beautiful solution, but sometimes it should be this way.
Thanks, Hendrik, i will try to implement your suggestions, and give you feedback.
I just finished my next blog, regarding the customizing part:
Have fun reading it,
Recently we had an Issue or rather trying to find a Solution for Tcode: SXI_MONITOR. I found the relevant API for the same but when i was debugging i found a Class CL_ECH_PPO_RETRY which is used reprocess PI Message.
When i tried to check in detail for this Class : CL_ECH_PPO_RETRY from a SAP Product Point of view , SAP design's this on basis of Design Pattern or Factory Pattern. Can some provide me documents or links through which i can Understand this as how this product development takes place. I am quite inquisitive to understand this..!
I have also opened a separate thread for the same --> https://answers.sap.com/questions/505906/abap-objects-design-pattern-factory-pattern.html
Any pointers or help, will be highly appreciated.