I am going to write a series of articles this year on my favorite topics of Distributed Computing, Java, Agile, NoSQL, and Garbage Collection (a series known as "DJANGO Untamed").
This is the first topic of the series where I will talk about Java Design Patterns.
We all want to be good programmers, but need proper guidance:
- Design Patterns often confuse us
- We know patterns, but hard to get that implemented
- Very few patterns come into implementation in the natural progression
- Vast online resources, but what should we follow?
Malcom Gladwell mentioned in his famous book "Outliers" (published in 2008) that it takes 10,000 hours of effort to achieve mastery at a professional level.
Can We Make the Problem Simpler?
If we can’t solve the problem, let's make it simpler.
Tied up multiple patterns in a single and simple example
Link with a real life problem
Why Design Pattern?
- Patterns are repetitive
- Patterns are proven
- Patterns are tested
- Patterns promote reusability and extensibility
- Patterns keep maintainability
- Separation of responsibility
What do We do in Software Programming?
1. Creates any activity or task to maintain a state (objects/holder)
2. How different actions (who does the activity or trigger it) are performed to do the activity
3. How the actions behave or interact with each other means what’s the behavioral aspect
Who Was the Pioneer?
Gamma et al described 26 patterns to accomplish above 3 core activity in software programming.
Erich Gamma, Richard Helm, RalphJohnson, John Vlissides known as “Gang of Four.”
Core Java Patterns, J2EE Patterns, EAI Patterns
Core Java Patterns
Creational, Structural, Behavioral
Core J2EE Patterns
Presentation Tier, Business Tier, Integration Tier (The specific patterns under each category are not mentioned)
Please visit the site http://corej2eepatterns.com/
There are many patterns in this space. (Please visit the site http://www.enterpriseintegrationpatterns.com/)
An AntiPattern is a literary form that describes a commonly occurring solution to a problem that generates decidedly negative consequences. (Reference: https://sourcemaking.com/antipatterns)
The purpose of this mention is to ensure that we are not using the design patterns in the wrong context which may take away the potential benefits and impose side effects.
A list of such development anti-patterns can be found at https://sourcemaking.com/antipatterns/software-development-antipatterns
Core Principles (SOLID)
A class should have only one reason to change.
Single Responsibility Principle
- A class should have only one reason to change.
Open Close Principle
- Software entities like classes, modules, and functions should be open for extension but closed for modifications.
Liskov’s Substitution Principle
- Derived types must be completely substitutable for their base types.
Interface Segregation Principle (Separation of Concern)
- Clients should not be forced to depend upon interfaces that they don't use. Don’t create fat interfaces just for the sake. Have a separate responsibility for each interface, but that should be limited to its boundary only.
Dependency Inversion Principle
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
- Design by Contract (Let's understand the responsibility between caller and callee and how the contract between these two should be followed)
- Convention over Configuration (Don't follow the configuration rather use a convention and let the platform do it for you. One of the most popular eCommerce Platform ("Hybris") uses this paradigm to simplify the development.
- Don’t Repeat Yourself (DRY) (A common example is to reduce the amount of Java comments when writing a JUnit test method. Let the name of the method depict what the method is intended to do rather than putting explicit comments)
- Active record pattern - The object encapsulates the behavior of a database record within it. It not only provides the access to the record but also gives the handle or method to manipulate that record. (See http://www.martinfowler.com/eaaCatalog/activeRecord.html)
- The Principle of Least Knowledge - Each unit should have minimum knowledge of other units and talk to immediate friends and not strangers. It is also called "Demeter Law". The principle promotes loose coupling.
Pattern and Principles – Who Will Win?
This is tricky to say who wins. Both and independent and inter-connected. Please find some common relations between the two.
- Patterns promote Principles
- Patterns follow Principles
- Patterns don’t compete with each other
- Patterns can be complementary and supportive of each other
Design Pattern Story
In the next, we will talk about a common design problem and how a team collaborated in a discussion to solve the issue.
- A famous US car company wants to build cars. It targeted 2 types of customers mainly, typical middle class and high flying “Fast and Furious” types.
- The company opened a manufacturing unit in Colorado Springs, Colorado.
- The unit started manufacturing these 2 type of cars (Sedan and Sports) started from designing, building, assembling, and decorating the cars.
- After 1 year of operation, the opened their first showroom in high hills of Rocky Mountain under the name “Garden of the Gods”.
- They may sell or lease the cars.
- hey collaborated with a local bank for financing the cars. Later, they have a plan to tie-up with other banks as well.
Flow of the Story – Start the conversation
John, the lead developer, on the project went to Jini, the lead Architect. John had few questions and doubts on common patterns, reusability, and best practices. John set a meeting with Jini in the WAR room with all the developers.
[The meeting starts] – Internal WAR room (10:00 AM CST)
John: Need a Car? So, we need a CarFactory first, right? Need 2 types of Cars (Sedan and Sports)
Jini: Should we use Factory or AbstractFactory? John : Obviously AbstractFactory
John: Building a car is a complex process. So, how can we create a complex object?
Jini: Should we go to a Builder and ask to build this complex object with its long-term experience?
John: Should we need a workshop in the Factory? I think we need only one Workshop.
Jini: Yes, we need only one. Oh! Should we use Singleton?
John: Once I build the car, I may need to add some extra functionality. But I don’t want to modify my class structure.
Jini: Yes, that is a valid question. We often need some wrapping functionality.
Tim (a senior developer): I heard of Decorator to wrap the object with additional responsibilities. Is that correct in this context?
John: Oh, yeah. Good guess Tim. You are a master of EJB. EJBHome and EJBRemote are examples of decorator pattern.
Jini: Wait a min…In order to decorate, you might need to get multiple design parts. How do you get those?
John: That’s simple. I will make sure that the client is not aware of complexities of getting data. He will just use what he/she gets. For him, I will provide a single call.
Jini: You got it. Let us use (pauses for a min)
Team (shouts): Facade pattern.
The team looks like better engaged after an hour discussion. But there was another meeting at 11:00 AM CST. So, the discussion was stopped and rescheduled for 2:00 PM CST again. John: Good afternoon guys. Hope all had a very good lunch. Let us come back to our discussion on patterns.
Jini: We covered till Facade.
Tim: I have a question. Once we have the car produced, there may be multiple designs what we may need to fit into. But there should be a base design as well as look and feel.
John: Oh, yeah. good question. What can solve this problem, team? Team (after a 2 mins pause): Don’t know.
Jini: How many of you worked in Apache velocity? Do you know what’s the purpose of it?
Tom (a developer) : Templating
Jini: Absolutely right. So, we should use some templates to provide partial overriding capabilities to the inherited classes without touching the base behavior.
Tom: So, we will use Template Method for some purposes like setting up Car stereo, GPS system etc. for different models under a particular category of car.
John: Next question pls…
Tim: We may need to fuse some incompatible behaviors across interfaces. So, we need a framework for building this conversion process from source to target system.
John: We definitely need an Adapter framework to bind across these multiple interfaces for easier translation and modularity.
Tim: Yes, that’s correct.
John: Next thing is we need multiple algorithms/logic to apply with each class having distinct responsibility. They should have their own strategy to accomplish the logic.
Tim: Need a strategy pattern (saying in a low voice)…
Jini (clapped): Good answer Tim.
Tom: Once we build the car, we may need not need to duplicate the same process. Can we just create a copy of the car to start with and then set required parameters/attributes as needed.This will reduce our effort of creating the car. Time is money :)
John : Yes, we can do that. But are you referring to prototype? If so, I am with you.
Jack, the marketing manager, wanted to listen to the discussion. So, he finished his lunch early and joined the conversation.
Jack: Guys, quick question. We need to sell or lease the car because we are talking to some car rental companies like Enterprise, Avis etc.
Jini: I got your intention, Jack. A very well thought question, though. Guys, we need a broker to simplify the communication between multiple participants. So, we definitely need to build a framework using command pattern to delegate the work to the needed entity by invoking its functionality.
John: Maybe Jini…
Jack: Looks like we got the answer. Another question?
Jini: Shoot Jack.
Jack: We will sell the car in the showroom. We are planning to open our first showroom in the midst of Rocky mountain. But we also want to have a rally scheduled next year to showcase the car. How do we deal with that?
Jini: No worries Jack. We will tackle multiple types of visitors without affecting the behavior of our showroom or rally. This is little tricky, but I think we can use Visitor pattern here. What do you think John?
John (Little fumbling): I need to look into that Jini. Can we take this discussion for later?
Jim, the financial officer, just came into the room. He was not much curious about this great discussion. But just wanted to clarify one quick question.
Jim: Jini, how are we planning to support for the financing of the car? You must be knowing that we have tied up with DCU bank for the car mortgage.
John: Yes Jim. It’s already on top of my head. We will use a mediator to facilitate the communication between the customer and the bank. So, that if we add another bank later customer can have multiple options to choose from instead of directly going to the bank.
Jini: I think that’s complete our query for today. It's already 4:00 PM CST. Let us meet after 2 days once you all put a thought over this discussion and come up with your questions. Please remember, you don’t need to use patterns just to use it. Use it whenever needed, but don’t overkill or over-engineer your effort if you can do the task in a simpler way.
The Final Cut
I iterate again on the core thoughts for applying any design patterns. Reusability Modularity Extensibility Flexibility
and follow proven thoughts instead of “reinventing the wheel”….. Good luck team.
Crux of the Core Patterns Used - Finding the domain and class hierarchies
AbstractCar – Abstract class for Car (Domain object)
SedarCar – Concrete implementation of a Sedan Car (Domain object)
SportsCar - Concrete implementation of a Sports (Domain object)
CarCarBuilder – Parent class in the Builder pattern
SedanCarBuilder – Concrete implementation of the abstract builder
Workshop – Director in the builder familyWorkshop – Uses Singleton since we need only one Workshop not multiple
IMovebleAbstractFactory – Base interface for Abstract Factory
MovebleAbstractFactory – Concrete implementation of Abstract Factory (producing SedanCarFactory and SportsCarFactory)
ICarDecorator – Base interface for decorating the Car
SedanDecorator – Decorates the sedan car
IRetrieveCarDesignPartsFacade – Parent class for Façade
RetrieveCarDesignPartsFacade – Concrete Implementation of Façade
AbstractCarAccessoriesAssembler – Abstract class for Template method
SedanCarAccessoriesAssembler – Concrete implementation of Template Method
ICarWashingProcessor – Base interface for Strategy
CarWashingStrategyImpl – Concrete implementation of strategy for washing the car
ICarEvaluationAdaptor – Base interface for the adapter pattern
CarEvaluationAdaptor – Concrete implementation of adapter
CarEvaluationAdaptee – Adaptee (encapsulate the Adapter)
CarBroker – Broker class in the Command pattern
CarTrade – Entity to trade (Domain object)
EnterpriseCarOrder or RetailCarOrder – Command invokers
ICarVisitor – Base interface for Visitor
SedanCarVisitor– Concrete implementation of the Visitor
ShowroomDisplay or RallyDisplay - Concrete implementation of the entities
ILoanMediator– Base interface for mediator pattern
LoanMediator– Concrete implementation of the mediator
CustomerParty– Source entity mediating through mediator
LoanParty – Target entity mediating through mediator (Domain object)
The following patterns were used to design the solution.
A creational pattern
Factories are source of creating/constructing objects
The client shouldn’t know how the objects are being created. They should only use it
Creates Product through Abstract Interface
Multiple interconnected factories with similar behavior
Need to create simpler objects without much complexities and dependencies
Car needs to be created for both sedan and sports types, so abstract factory combines factories with similar behavior (both are cars only)
Drives Single Responsibility Principles since each factory has own responsibility
Factories are always better way to produce mass objects
A creational pattern
Builder is used to create complex objects through the creation of different objects
Build objects one step at a time instead of creating in a single step
Isolate code for construction over representation
Algorithm of creating objects should be independent of both the parts which make up the object and how the parts are assembled
Need to create simpler objects without many complexities and dependenciesØRemove the use of multi-parameter use of constructors
The construction process must allow different representations for the object that's constructed.
We need to build a Sedan Car but it needs several small parts to be assembled and this process should be independent of how the Car was created.
Building an object in step-by-step process is necessary
Sometimes building an object is complex than just to use Factory
A creational pattern
Creates a single instance and provides a global point of access
Controlled access to sole instance
No need to create individual instance of the object
We need to build the car in a Workshop. Do we need to separate workshops for building/assembling the cars? Really not, because we can use one Workshop to do the job.
Promotes reusabilityManages objects efficiently whenever needed
A Word of Caution
Be aware of the "double check locking" problem with Singleton. There are alternate ways to handle this. One of the popular way to handle through Singleton Enum (A good article presented by Mainak on DZone - https://dzone.com/articles/singleton-design-pattern-%E2%80%93)
A structural pattern
Works as a wrapper
Attach additional responsibilities to an object dynamically
Provide a flexible alternative to subclassing for extending functionality
Need to add new functionality an existing object without altering its structure
Need to decorate the class. Could have been added a decorator functionality to the Car class through subclassing? But can that be managed externally to add dynamic responsibility to the Car class? CreatedSedanDecorator to decorate the sedan car. Decorating the sedan car can be different from the sports car.
Promotes less cohesion and loose couplingSubclassing makes the object hierarchy complex
A structural pattern
Need to hide the backend complexities from the client
Client needs a simple interface to do complex processing without much latency and network overhead
Need to club together multiple iterative calls from client to server in order to reduce the number of interactions between the client and server over the network
The design parts for car needs to be retrieved from multiple different external systems/vendors. Should we retrieve them one by one from the client side or retrieve all the information from server side transparently by providing a single and simple interface to the client but with the same results?
Provides efficient usage of network
A behavioral pattern
Needs some common logic across the object hierarchy through inheritance from parent class
Lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
Multiple subclasses need to inject their own implementation logic and override some part of the algorithm
The core logic for the assembly of the car accessories may be common but may differ in few places depending on whether this is a Sedan or Sports car
Promotes separation of concern
Avoids code duplication by putting the common code in a single place
A structural pattern
Allows incompatible interfaces to communicate and interact together
Allows reusability of older functionality (legacy interfaces)
Need to talk to another interface but the languages/structures are different between the source and target systems
As a quality check, the car needs to be evaluated against some external parameters. But the target system’s interface is different than what the Car system understands. So we need some intermediate entity to bridge that gap. That’s where we need an adapter.
Promotes loose coupling and reusability
A behavioral pattern
An alternative to subclassing
A set of possible behaviors needs to be applied in an application to change its functionality
When the conditional statements are needed but don’t need to put in a single class
Need different variant of an algorithm
SedanCar may have a different strategy to wash the car than the SportsCar. Should we create different strategies?
Drives Single Responsibility Principles since each strategy drives their own version of the algorithm
A creational pattern
A way to duplicate objects without knowing how to create those
Need to create objects at run timeØSpecifying new objects by varying values or structures
Creating a Car for Demo purpose in the showroom can be done by prototyping the actual car
A behavioral pattern
Triggers some instructions to another class by invoking operation
Encapsulates a request in an object to store any command and then pass to a method and return the command like any other objects
Separates the object that invokes the operation from the one that knows how to perform it
Need a CarBroker who can trade the car for retail or enterprise customers, but the trader should know how to do it
Promotes loose coupling
A behavioral pattern
Defines a new operation without changing the classes of the elements on which it operates
Need to define new operations over the elements of the structure of the objects
Need the car visitors for Sedan type in different places like the showroom or rally.
A behavioral pattern
Manages communications through a single object and distributes messages among other objects
A set of objects need to communicate but not in coupled way
Need to process for car loan but it is better to process through a mediator who communicates between the client and the bank
Simplifies object protocol
Centralized control for communication
A Sample UML Class Diagram
Maven project for the code on GitHub