File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes OO, Patterns, UML and Refactoring and the fly likes Stratergy vs Factory method vs Template method patterns Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Stratergy vs Factory method vs Template method patterns" Watch "Stratergy vs Factory method vs Template method patterns" New topic
Author

Stratergy vs Factory method vs Template method patterns

Kamal Mettananda
Ranch Hand

Joined: Oct 25, 2005
Posts: 51

Hi all,

I'm doing a design and have to make a decision at a point on which way to go.

Following is the situation.

1. Our application talk to another existing application.
2. Our application and their system have a set of matching objects for communication.
3. Our app talk to their app by passing objects that they are expecting, so they return results in their format. Then we convert the returned results back to our types.
4. I'm writting a generic code to match all record types. My code will be as follows.



So I need those two convert() methods implemented for each of the record types.



Record types are like; TheirEmployee/OurEmployee, TheirCompany/OurCompany, etc.

Options to go with:
Create an interface called; Converter with two convert() methods and concrete classes like EmployeeConverter.

1. Stratergy pattern
Add a Converter type instance variable to ExchangeData class and initialize with correct type using constructor.


2. FactoryMethod
Add a method called createConverter() to ExchangeData class; and subclasses create correct instances of the Converter.



3. Template Method
Make those two convert methods in ExchangeData class as abstract (template methods) and let the subclasses implement those as needed.

Which one should I choose? Or what are the pros/cons of going with each option.

Any idea will be helpful.

Thanks.
[ January 22, 2008: Message edited by: Kamal Mettananda ]

Kamal Mettananda - SCJP 1.4 (98%)
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Am I understanding correctly that ExchangeData is the class of the objects that will be passed between the applications (a DTO)? Then I would say that it shouldn't know at all about the conversion to application specific objects - that is, none of the three options sound optimal to me.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Kamal Mettananda
Ranch Hand

Joined: Oct 25, 2005
Posts: 51

Originally posted by Ilja Preuss:
Am I understanding correctly that ExchangeData is the class of the objects that will be passed between the applications (a DTO)?


Hi Preuss,

I'm afraid, that's not a DTO object. Let me try to clarify this a bit more.

My application needs to call different functions from another application; like add(), update(), search() etc.

So for that I have client's jar with Client classes.
eg: TheirEmployee, TheirCompany and all of these extends from a super class called TheirRecord. Also we have created matching classes for those like; OurEmployee, OurCompany. (This will decouple our code from their code a bit).

They have methods with super type parameters. eg:


So we need to call those methods, but the problem is we have to convert our objects into their matching ones (functionality of convert() method).

My application create a OurEmployee and we need to call addRecord() and get the resulting status from them.

So following is what I feel as the process.

1. Convert OurEmployee to TheirEmployee (populate a new TheirEmployee instance using our values).
2. Call their addRecord() like function.
3. Convert TheirStatus to OurStatus (populate new OurStatus using their returned instance).

So I felt that this logic is not going to change between different object types like Employee, Company, etc; but the conversion is changing.

I think it's more clear now. Would you discuss this a bit more and help me to understand how to solve this type of a situation?

This discussion will help me in doing any design.

Thanks.
Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
This seems simple enough that I don't even think a pattern is necessary here. You can make it the responsibility of each object to convert itself into the other format:



I guess first you would need to either create interfaces (or add methods to existing ones) for both MyObjects and YourObjects:



So now you've got objects that know how to convert themselves into the other guy's format. It should be pretty easy to communicate with the other party now:



Still a little complicated I guess but using this way there are no external Converter objects or factories to create those objects. The key here is that each object is responsible for converting itself into its counterpart.
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2922
    
    5
Originally posted by Kamal Mettananda:
Hi all,

I'm doing a design and have to make a decision at a point on which way to go.

Following is the situation.

1. Our application talk to another existing application.
2. Our application and their system have a set of matching objects for communication.
3. Our app talk to their app by passing objects that they are expecting, so they return results in their format. Then we convert the returned results back to our types.
4. I'm writting a generic code to match all record types. My code will be as follows.


Actually given this description I would think that you should first focus on a facade for your application. That way your application only has dependencies on it's own classes and the facade, not the all those converters and even possibly their classes. Those converters belong on the other side of the facade. The facade is part of your application's anticorruption layer so that it can evolve independently from any encumbrances that the other application's design may place on it.

Remember observance of the Object-Oriented Design Principles is ultimately more important than the repeated application of some core design patterns.
Kamal Mettananda
Ranch Hand

Joined: Oct 25, 2005
Posts: 51

Originally posted by Timothy Frey:

The key here is that each object is responsible for converting itself into its counterpart.


Hi Thimothy,

This sounds good. But I have some concerns.

TheirObject and their subclasses like, TheirEmployee are created by them. So I can not change those. Basically I can not let TheirEmployee to have a method called convert() to convert itself to MyEomployee.

That's why I suggested a Converter interface with two convert methods and sub classes of Converter will do conversion depending on the object received.



So if I happened to create different convertor methods or subclasses, I will have to go with one of the methods I suggested? What would you suggest?

Thanks.
Kamal Mettananda
Ranch Hand

Joined: Oct 25, 2005
Posts: 51

Originally posted by Peer Reynders:

Actually given this description I would think that you should first focus on a facade for your application.


Hi Peer,

Not sure how Facade would apply in this case. As I know mainly facade applies in simplifying a complex interface.

Would you elaborate?

Thanks.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
(I think) I agree with Peer here. The best solution would be one where your application and the other application would be totally independent of each other, that is, your application classes shouldn't know anything about classes of the other application and vice versa.

You could introduce a Facade that hides the other application (which I get is running in the same JVM?), translating calls to appropriate calls to the other application and converting objects while doing so.

Does that make sense so far?
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2922
    
    5
Originally posted by Kamal Mettananda:
Not sure how Facade would apply in this case. As I know mainly facade applies in simplifying a complex interface.


In a "simple" use of a facade (your are saying that both application "models" are fairly similar, resulting in a one-to-one mapping of the classes) the facade would hide from your application the fact that conversion is even necessary, so that the "complexities" of conversion won't invade your application.

In a fullblown anticorruption layer the role of the facade is slightly different. There the facade facilitates and streamlines access to the features of the other application that are required while it hides the rest (encapsulation of the other application). Your application only accesses the services (which are based on the model of your application) of the anticorruption layer. These services delegate to adapters (which support the service interface but know how to make equivalent request on the facade). The adapters themselves delegate the task of translation to translators. A fullblown anticorruption layer gives your application the opportunity to evolve its object model independently from the other application. This of course comes with the price of maintaining the anticorruption layer. It does however separate concerns and responsibilities very nicely:
  • Your application: Your object model, your business logic.
  • Anticorruption layer: mapping of requests and object models, no business logic.
  • Other application: Their object model, their business logic.


  • Here is a case study for an anticorruption layer: IAnticorruption � A Domain-Driven Design Approach To More Robust Integration (PDF) from domaindrivendesign.org.

    In any case, without the use of a facade you run the real risk that your business logic will become entangled with the conversion logic/objects.
    [ January 24, 2008: Message edited by: Peer Reynders ]
    Kamal Mettananda
    Ranch Hand

    Joined: Oct 25, 2005
    Posts: 51

    Hi Peer,

    Thanks for all your help. But I'm not that fit with DPs, so I could not grab what you mean. Anyway I'll check that doc as well.

    Would you be able to explain these against my current problem? Or using a sample problem?

    Thanks.
    [ January 28, 2008: Message edited by: Kamal Mettananda ]
    Roger Chung-Wee
    Ranch Hand

    Joined: Sep 29, 2002
    Posts: 1683
    This is how I tend to look at this kind of situation.

    Create a Facade class which would provide the single interface for your app. The Facade might have a method declaration like this.



    So, you invoke the method by doing new Facade().addRecord(...).

    This method would convert OurRecord to TheirRecord, invoke the other app's addRecord() and convert the TheirStatus response to OurStatus response.

    Note that the Facade does not have to do the object conversions, these tasks can be delegated to a Conversion class.

    If the definition of TheirStatus or TheirRecord should change, your client will not know about it if only the Conversion class has to change.

    Does that help?


    SCJP 1.4, SCWCD 1.3, SCBCD 1.3
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    I think Roger is dead on.
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2922
        
        5
    Originally posted by Kamal Mettananda:
    Would you be able to explain these against my current problem?


    You actually have presented a partial solution rather than the actual problem that needs to be solved. It isn't even clear what the respective problem domains of "your" and "their" application are, so there is no way to tell whether "a set of matching objects for communication" occurs naturally between both applications or whether the assumption is being made that a partial type harmonization would make the job easier without necessarily considering the potential constraints that this may place on "your" application.

    Or using a sample problem?


    Well, here is a contrived and oversimplified one:

    Lets say "our" application has a Customer class with a purchaseLimit attribute. Considerations of "credit" are only of peripheral interest to "our" application. However when a change in the purchaseLimit is made it cannot exceed the current credit limit (that is the credit limit has to be retrieved at the time when the request to change the purchase limit is made). Furthermore our customer class will not hold a credit card number (1. credit is only of peripheral interest to "our" domain 2. for "security/privacy reasons"), though one of "our other" systems has one on hand.

    "Their system" has the credit limit. It is stored on "their Client class". We don't have "their Client ID" - however we can obtain it from "their CreditCard" with the "CreditCardNo" stored in "our other" system.

    So while "our Customer" and "their Client" are roughly equivalent we have to use additional information on "our side" and an additional object on "their side" (their CreditCard) to make the link. And because of the reasons stated above it makes no sense to convert or merge "their Client" into "our Customer", both of these objects serve completely different domains.

    (The code samples are not fit for any purpose other than the illustration of the "happy path" collaboration of the objects involved).


    Output:



    The Customer class is simply


    and uses


    A translator can be used to convert the Customer ID to a credit card number.


    Now we have all the pieces for "our facade"


    Pros: Consumers of the facade ("our Customer") are not exposed to the objects in "their domain", they don't have to deal with information that may be split over multiple of "their objects".

    Cons: In this particular case the logic is manageable and some of the potentially "complicating" logic has already been factored out and delegated into the translator so that the facade doesn't have coordinate the translation itself (which requires knowledge of "our other" system). However the facade implementation is mixing objects from both domains ("our Customer", "their CreditCard and Client") and addressing complexities of "their" domain simultaneously, which in more elaborate systems can quickly lead to unmaintainable code. This is exacerbated as "our domain objects" which exist inside of the facade implementation will have a tendency to attract "our domain logic" into the facade (which also dilutes our domain model).

    So ideally you want the facade to structure (which sometimes means simplify) "our access" to "their systems" as we need it. To control complexity of the facade it should deal with "their systems" on "their terms", it shouldn't have to worry about "our domain objects". But we don't want to pollute "our domain objects" with "their domain concepts" just so that we can use the facade implementation. That is where the Anticorruption Layer comes in.
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2922
        
        5
    An Anticorruption Layer is roughly:

    Our App (Our Domain)
    =======ACL start====
    Services
    Adaptors - Translators
    Facade
    ========ACL end=====
    Their App (Their Domain)

  • Facade - Structures access to "their app domain" in terms of the calls that the Services offer in "our domain" without actually converting any objects.
  • Adaptors - Convert calls from the Service to the facade. Object conversion is delegated to the translators.
  • Translators - Convert domain objects and values across domains (but don't convert calls).
  • Services - Offer non-Entity functionality to the domain model. Selects the appropriate adaptor and may collect additional information from "our domain" before making the call.



  • The first step towards building an Anticorruption Layer from the previous facade implementation is to strip out "our domain objects" so that the facade only deals with "their domain concepts".

    (Again, the code samples are not fit for any purpose other than the illustration of the "happy path" collaboration of the objects involved.)


    Note that the getCreditCardLimit method accepts a creditCardNo instead of a customer. So there are no longer any of "our domain objects" here that may require handling by "our domain logic".

    Meanwhile the Customer no longer accesses the facade directly; it now uses a Credit Service instead.

    In Domain Driven Design (DDD) your domain concepts are classified as Value Objects or Entities. Any concepts that can't be elevated to a full-blown Entity usually end up as Services. I earlier stated that "credit" is only of peripheral concern to "our domain" - so now we have a "CreditService". In this case CreditService is our application's entry point into the Anticorruption Layer. A Service will tend to contain domain logic so it is part of the "our domain model". An Anticorruption Layer can have more than one Service depending on the scope of "their application". The CreditService uses adaptors to do any work that is not related to "our domain model". These adaptors only accept and return "our domain objects".


    Adaptors deal with part of the cross-domain issues. They control complexity by:
  • Focusing on a very narrow aspect of the cross-domain exchange (in this case obtaining a credit card limit).
  • Delegating the actual mapping/conversion of incoming and outgoing objects/values to translators.


  • In this example the adaptor only uses one translator, but in many cases it will use a number of translators. Its responsibilities are very focused:
  • It accepts "our domain objects" as method arguments.
  • It uses the appropriate translators to perform the conversion to "their domain objects"
  • It calls the appropriate method with "their domain objects" on the facade.
  • It uses the appropriate translators to perform the conversion of the result(s) to "our domain objects"
  • It returns the relevant "our domain objects" as the result.


  • The translators deal with the remaining cross-domain issue - domain object conversion. Note that it may take multiple input objects to create one output object and one input object could result in multiple output objects. The translator should be given all the input objects it needs; so the service should collect any additional information from the domain that is needed before it calls the adaptor that uses the translator. Similarly the facade needs to deliver all of "their domain objects" to the adaptor that will be required by the translators. If the translator needs assistance not related to either domain then it has to get that assistance itself (in our example the CreditCardNoStorage).
    [ January 30, 2008: Message edited by: Peer Reynders ]
    Kamal Mettananda
    Ranch Hand

    Joined: Oct 25, 2005
    Posts: 51

    Hi Peer,

    Thanks a lot for this huge time and knowledge spend on helping me. This is a great discussion and I'm learning a lot.

    I spend much time with this example to grab as much, and clear to me.

    So the main focus is on; separating the client-domain from our-application-domain. And facade is the only place where we have all client-domain dependent stuff.

    I did the design for that project as follows without this knowledge. It looks as follows. It's a bit lengthy, but if you can please go through these and provide me with some more help.

    This is the task: Import in instance of a subclass of ClientRecord into main system (some outside application) and return the result as ClientResult.

    ClientRecord and subclasses.


    Main system has record types as sub types of SystemRecord class, and there are classes like SystemCustomer, SystemContact. But there's no guarantee of one-to-one mapping.

    Plan to use RecordConverter subclasses for the conversion process.


    Converting Add Result



    Import any subtype of ClientRecord into main system and return the results as ClientResult.



    By analyzing these classes, I found that following classes are dependent on the main System's types.
  • RecordConverter and all subclasses
  • RecordConverterFactory
  • ClientResultConverter
  • RecordImporter

  • Which means all the classes in Client side application are dependent on main Systems types.

    So after all it seems that this design isn't good. Please let me know your advices.

    Thanks a lot.
    [ February 14, 2008: Message edited by: Kamal Mettananda ]
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2922
        
        5
    Originally posted by Kamal Mettananda:
    Which means all the classes in Client side application are dependent on main Systems types.


    Not exactly. ClientResult, ClientRecord, CustomerCRecord and ContactCRecord don't have any direct dependencies on the main system types. Your RecordImporter is essentially a client-facing adapter (adapting ClientResult addRecord(ClientRecord crec) to SystemResult addRecord(SystemRecord srec)). To further decouple the client domain RecordImporter should actually be an interface


    That way whatever uses the adapter has dependences on the "Client-based" parameter and return types and the adapter interface (ClientRecordImporterAdapter) which should be injected during construction - dependencies towards classes that are needed to create the ClientRecordSystemsImporterAdapter are avoided.

    Inversion of Control Containers and the Dependency Injection pattern
    Why is dependency injection better than a factory

    I'd be inclined to lose the RecordConverterFactory and those instanceofs in a hardcoded conditional bother me. Modifying or extending ClientRecord to give you the correct converter isn't an option (not part of their domain) so I can't see how you can get rid of using instanceof. However the more extensible approach is to get the converter to tell you whether it can deal with the subclass:


    Now you can create both CustomerConverter and ContactConverter up front and add them to an ArrayList<RecordConverter>. Then you pass this List<RecordConverter> into the ClientRecordImporterAdapter constructor instead of the RecordConverterFactory. In addRecord you simply iterate through the List<RecordConverter> until you find one that "canConvert".

    Note that your current design seems to imply a push architecture - the client pushing data into your system rather than the system pulling the data in that it needs. You may want to look at the Dependency Inversion Principle if you intent to import data from multiple sources.

    http://www.coderanch.com/t/100554/patterns/Java-Batch-Program-Design#000005
    [ February 14, 2008: Message edited by: Peer Reynders ]
    Kamal Mettananda
    Ranch Hand

    Joined: Oct 25, 2005
    Posts: 51

    Originally posted by Peer Reynders:


    To further decouple the client domain RecordImporter should actually be an interface.
    .... However the more extensible approach is to get the converter to tell you whether it can deal with the subclass:


    Yes, I got your points. I'll make those change. So the implementation would be as follows?




    Now I should aggregate these and present the client with an API to call. For that I created an Integrator interface.



    This interface will be implemented as follows to deal in implementations.



    Now should we provide a factory method to strict their access to SystemHandler implementation?




    Would this be the way to go?

    Thanks.
    [ February 14, 2008: Message edited by: Kamal Mettananda ]
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2922
        
        5
    Returning null in ClientRecordSystemsImporterAdapter.addRecord is the way to tell that there was no matching converter? That means lots of ugly checking for null will be necessary. If you don't want to throw an exception at least return a NullObject (you only need one instance) or in your case a NullClientResult.

    Note that SystemHandler/SystemHandlerImpl is your facade implementation.

    In my opinion you have made SystemHandlerImpl unnecessarily dependent on CustomerConverter, ContactConverter, ClientResultConverter, SystemImporter and ClientRecordSystemsImporterAdapter when it only needs to depend on ClientRecordImporterAdapter.



    1. By making SystemHandlerImpl only dependent on interfaces you can more effectively unit/integration test. For testing you can create decorators for RecordConverter and ClientRecordImporterAdapter (SystemImporter, ResultConverter if you introduce an interface for them) that track if, when, and how the implementing class was accessed giving the unit test the opportunity to check not only the end result but also whether the invocation was processed as planned (Whether that is necessary here is debatable). More importantly it gives you the opportunity to use a FakeSystemImporter (totally memory based and pre-loaded by the unit test setup) so that your unit tests will run faster than with the real system/database backed SystemImporter.

    2. For simple classes its not unusual that they are responsible for their own construction/initialization. However as classes get bigger construction and assembly gets more complicated and becomes a separate responsibility in its own right (Single Responsibility Principle - SIP). You were already planning on a factory anyway so you might as well give it something to do - configuration of the facade implementation.



    You may have a good reason for using a factory - however the main reason usually cited is "needing a global accesspoint". Next thing the Factory will be turned into a Singleton with all its warts (Just Create One is better). So I'd prefer that the SystemHandler is assembled during startup and injected into the classes that need it.




    Another option is to defer construction to a subclass:



    That way construction/assembly is the responsibility of StandardSystemHandler while SystemHandlerImpl is doing all the real work against the general interfaces and SystemHandlerImpl can still be unit tested with fake/mock implementations of the classes it delegates to.

    Note however that with this subclass there is as much a temptation to use it mid-stream, out of nowhere (just like the factory) making it difficult to bring code using it under unit test. So it still requires some discipline to use it properly.


    [ February 15, 2008: Message edited by: Peer Reynders ]
    Kamal Mettananda
    Ranch Hand

    Joined: Oct 25, 2005
    Posts: 51

    Originally posted by Peer Reynders:
    If you don't want to throw an exception at least return a NullObject (you only need one instance) or in your case a NullClientResult.


    Ok, I'll try that.


    In my opinion you have made SystemHandlerImpl unnecessarily dependent on CustomerConverter, ContactConverter, ClientResultConverter, SystemImporter and ClientRecordSystemsImporterAdapter when it only needs to depend on ClientRecordImporterAdapter.


    True, but there needs to be some place where this dependency exists. I created the SystemHandlerImpl for creating the ClientRecordSystemImporterAdapter with other instances. But SystemHandlerImpl has another responsibility (which I didn't recognize earlier); run those operations like add, addList. So I understand that you have separated the complex creation of SystemHandler with ClientRecordSystemImporterAdapter responsibility to a new factory.

    With StandardSystemHandlerImpl and SystemHandlerImpl also you are separating those responsibilities to two classes by sub classing. I would prefer the first version as I think, association would be better than inheritance.

    So we'll be asking to client to use the Factory to get access to the SystemHandler as;





    So I'd prefer that the SystemHandler is assembled during startup and injected into the classes that need it.



    So how are we planning to ask the client to use Applcation class to get a handle to SystemHandler, with which method? I could not understand this Application class's assembleApplication and runApplication methods. Would you elaborate?

    No idea about the following code fragment.



    (requiresSystemHandlerInstance and RequiresSystemHandlerClass ?)



    1. By making SystemHandlerImpl only dependent on interfaces you can more effectively unit/integration test.


    You have provided some hints on unit testability with decorators. I'm not that familiar with it (I'm familiar with unit testing with Junit just by populating concrete classes. But not sure how to use decorators). If you can give me some hint on that as well using this discussed code, that's great.

    Thanks a lot.
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2922
        
        5
    Originally posted by Kamal Mettananda:
    Ok, I'll try that.


    Note that you can implement a null object as an anonymous class:


    So we'll be asking to client to use the Factory to get access to the SystemHandler as:


    Now granted Effective Java states "Item 1: Consider providing static Factory methods instead of constructors". However back in 2001 JUnit/unit testing wasn't as widely spread as it is today. Factory methods are still a good idea however they shouldn't be static and they should implement a method on an interface so that special unit testing factories can be injected for unit testing. Working Effectively with Legacy Code explains quite well how code needs to be structured to be brought under unit test (Any code not currently under unit test is considered legacy code - even if you just wrote it yesterday).

    So we'll be asking to client to use the Factory to get access to the SystemHandler as


    By only giving a global static access point you are limiting the options for unit testing within the client application. They are going to have to write a wrapper around the global static access point. It is less work for them if you provide a pre-packaged "factory class" which implements an interface:



    That way they can create their own SystemHandlerFactory for unit testing or instrument yours if they feel that it is necessary.


    No idea about the following code fragment


    It simply illustrates that you should be explicit about the dependencies that your class has, especially if the class that you depend on "encapsulates" an external (e.g. DB) or remote system. Unit testing is made more difficult if your code obtains that dependency "midstream" either through some static access point or by creating the concrete class explicitly. Unit testing is simplified if the dependecy is implemented against an interface and not a concrete class and if the concrete class is injected during construction (example: RequiresSystemHandlerClass constructor) or configuration (example: requiresSystemHandlerInstance setter).

    You have provided some hints on unit testability with decorators.


    Unit Testing With Hand Crafted Mocks. The Counter, Store and Printer mocking idioms use the decorator pattern.
    [ February 18, 2008: Message edited by: Peer Reynders ]
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Stratergy vs Factory method vs Template method patterns