18 Jan 2014

(Design Patterns) Method Template Example in Backend Side


  •  Advance:

I assume I don’t need to tell you what a Design Pattern is and how it works. I suppose if you’re reading this post it’s because you have knowledge about the commons Design Patterns (MVC or DAO for example).

Inside the set of Behaviour Patterns, we can find the “Method Template” Pattern (in Wikipedia we can find a good explanation about this Pattern, what is the main objective of the Pattern and how is the strategy that this Pattern follows)


But if you don’t want to read it I’ll resume to you. This pattern starts from an abstract idea but with the knowledge about how many steps an algorithm must follow. Starting from this abstract idea, you can develop your code in all the concrete levels as you need to develop your application.

Talking about code, the strongest point of this Pattern is the reusability when you know your application must follow the same steps for all your entities with little differences. It’s usual to use this pattern in addition with the FactoryPattern or the Service Locator Pattern (about Service Locator Pattern, a lot of people don’t consider it as a Pattern and they prefer talk about it as a AntiPattern  we should discuss about this in another post)

In this post you can find a running application just for seeing how the application works under this design pattern. You can check the code in this revision of the next SVN address:

Rev: 4

  • Explanation

My code talks about a Service, and this Service uses  a Facade for the management of Vehicles (only two kinds of vehicles because I only used two abstractions levels for my example). The Service is not implemented yet but just launching the Tests inside the application, you will see an example of this pattern, also you will understand how it works and the benefits this idea could give you in your future applications.

For the checkout of the code, you should know this example was developed as a MavenProject, under the 1.7 JDK using Spring 3 annotations.

About the application, the main idea is a Facade using a ServiceLocator to get an instance of an Interface. This interface is implemented by an Abstract Business class which defines the main steps of the algorithm to validate and to execute a vehicle. But at the end of these methods the Abstract Class calls to an abstract method named “methodConcrete”.

You can find two concrete implementations of the Abstract class; in this Concrete class (one for Engine Vehicles and another one for Animal Vehicles) you just can see we only have to develop the abstract “methodConcrete” defined in the Parent Class.

My code was built so fast so you can see the database is simulated by a HashMap and I use a Service Locator as a Factory. But this is just the beginning, in future post I will include improvements as a clean Spring FactoryBean and an embebed database using JPA annotations.

    • API Tier



Object
Description

TemplateDTO
Data Transfer Object.
This object will be used as a template for all the Data Transfer Objects of my app. Will be used for the definition to make an Interface which use Generics.
VehicleDTO
Data Transfer Object.
This object will be used as a container of all the common attributes to define a Vehicle.
EngineVehicleDTO
Data Transfer Object.
This object will contain the concrete attributes for an engine vehicle.
AnimalVehicleDTO
Data Transfer Object.
This object will contain the concrete attributes for an engine vehicle
VehicleEnum
Enumeration.
This Enumeration will be used to select a template for working. In each label we can find an attribute called “service” used to locate the specific business bean.

    •  SERVICE Tier (Service Implementation not implemented)



Object
Description

VehicleFacade
Facade for a non-existing service. This facade uses a Service Locator object to find the concrete business bean to be used.

If any error appears, will throw a FacadeException

    • BUSINESS Tier


Object
Description

TemplateBusiness
BusinessObjectGeneric interface to define a generic API for all the objects which extend from TemplateDTO
AbstractVehicleBusinessImpl
BusinessObjectAbstract class which implement the TemplateBusiness and which define the main steps of the two operations, “validate” and “execute”.
EngineVehicleBusinessImpl
BusinessObjectConcrete Business class to define the concrete steps for the validation and execution of a Engine type vehicle
AnimalVehicleBusinessImpl
BusinessObjectConcrete Business class to define the concrete steps for the validation and execution of a Animal type vehicle

    • Code snapshots


VehicleFacadeImpl

@Override  
      public void manageVehicle(VehicleDTO vehicle, VehicleEnum template)  
                throws FacadeException {  
           if (template == null) {  
                throw new FacadeException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_TEMPLATE_NOT_INFORMED));  
           }  
           @SuppressWarnings("unchecked")  
           TemplateBusiness<TemplateDTO> templateBusiness = this.templateServiceLocator  
                     .getTemplate(template.getService());  
           try {  
                templateBusiness.validate(vehicle);  
                templateBusiness.execute(vehicle);  
           } catch (BusinessException b) {  
                throw new FacadeException(  
                          MessageUtils.getMessage(MessageUtils.ERROR_VEHICLE_WRONG),  
                          b);  
           }  
      } 

As you can see, using this pattern we can reutilize code a lot, because we don’t need different methods for each kind of vehicle. Just we can use only one method specifying the template to used.



AbstractVehicleBusinessImpl<T extends VehicleDTO>

 @Override  
      public void validate(VehicleDTO element) throws BusinessException {  
           if (element == null) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_VEHICLE_NOT_INFORMED));  
           }  
           if (StringUtils.isBlank(element.getName())) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_VEHICLE_NAME_ISEMPTY));  
           }  
           if (StringUtils.isBlank(element.getDescription())) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_VEHICLE_DESCRIPTION_ISEMPTY));  
           }  
           try {  
                this.validateConcrete(element);  
           } catch (ClassCastException c) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_ELEMENT_NOT_COMPATIBLE));  
           }  
      }  
      @Override  
      public void execute(VehicleDTO element) throws BusinessException {  
           if (element.getIdVehicle() != null  
                     && storedVehicles.containsKey(element.getIdVehicle())) {  
                throw new BusinessException(  
                          MessageUtils.getMessage(MessageUtils.ERROR_ELEMENT_EXIST));  
           }  
           List<Integer> keysStored = new ArrayList<Integer>(  
                     this.storedVehicles.keySet());  
           Collections.sort(keysStored, new Comparator<Integer>() {  
                @Override  
                public int compare(Integer o1, Integer o2) {  
                     return o1.compareTo(o2);  
                }  
           });  
           element.setIdVehicle(keysStored.get(keysStored.size() - 1) + 1);  
           try {  
                this.executeConcrete(element);  
           } catch (ClassCastException c) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_ELEMENT_NOT_COMPATIBLE));  
           }  
      }  

In this abstract class we’re reutilizing code so much because we validate the common attributes to all the differents kinds of vehicles. When we’re executing the “execute” method, we can see we have the common business logic (validate if an id exists in the system) in this abstract class delegating the concrete business logic (or validations) in all the objects which extend from this abstract class



EngineVehicleBusinessImpl

 @Override  
      public void validateConcrete(VehicleDTO vehicle) throws BusinessException {  
           // TODO Auto-generated method stub  
           EngineVehicleDTO engineVehicle = (EngineVehicleDTO) vehicle;  
           if (engineVehicle.getcV() == null  
                     || engineVehicle.getcV().compareTo(BigDecimal.ZERO) < 0  
                     || engineVehicle.getcV().compareTo(BigDecimal.ZERO) == 0) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_ENGINE_POWER_INCORRECT));  
           }  
      }  
      @Override  
      public void executeConcrete(VehicleDTO vehicle) {  
           EngineVehicleDTO engineVehicle = (EngineVehicleDTO) vehicle;  
           super.getStoredVehicles().put(engineVehicle.getIdVehicle(),  
                     engineVehicle);  
      }  

Here we have all the concrete steps for an Engine vehicle. You can see we only have to put in these methods all the things relative to the management of our concrete DTO (in the case of validation), and in the execute we only need to put steps related to the store of the vehicle in the place defined for it. But really all the logic is defined in a high level abstract template. Reaching this point, maybe we could introduce new abstraction levels following the same idea presented in this example. The JVM at runtime will know what concrete object must be used, because all of them are part of the same object family.



AnimalVehicleBusinessImpl

 @Override  
      public void validateConcrete(VehicleDTO vehicle) throws BusinessException {  
           // TODO Auto-generated method stub  
           AnimalVehicleDTO animal = (AnimalVehicleDTO) vehicle;  
           if (animal.getKindVehicle() == null) {  
                throw new BusinessException(  
                          MessageUtils  
                                    .getMessage(MessageUtils.ERROR_ANIMAL_NOT_INFORMED));  
           }  
      }  
      @Override  
      public void executeConcrete(VehicleDTO vehicle) {  
           AnimalVehicleDTO animal = (AnimalVehicleDTO) vehicle;  
           super.getStoredVehicles().put(animal.getIdVehicle(), animal);  
      }  

Here we have all the concrete steps for an Animal vehicle. You can see we only have to put in these methods all the things relative to the management of our concrete DTO (in the case of validation), and in the execute we only need to put steps related to the store of the vehicle in the place defined for it. But really all the logic is defined in a high level abstract template. Reaching this point, maybe we could introduce new abstraction levels following the same idea presented in this example. The JVM at runtime will know what concrete object must be used, because all of them are part of the same object family.

  • Conclusions

You can get conclusions by your own, the main idea all the benefits of this pattern was explained all around the post. Using this idea you make your code reusable, and you can introduce concrete objects in the application, which start from an abstract idea. That concept of abstraction gives you freedom to model at your interest, but I should advice maybe it’s not a good idea to introduce so many levels.

From my point of view, the weakness of this pattern would be:

  1. Excessive coupling between the concrete elements and the high levels object, because all of them must be part of the same family.
  2. Depending about how many levels you need to introduce in the family, the debug from the top level to the concrete level sometimes is hard to follow (is not easy to debug)
  3. If you introduce a new method in one of the high level objects, you should introduce the expected behaviour in the low levels objects. In other words, the pattern doesn’t have enough scalability.

No comments:

Post a Comment