First let's talk about design patterns itself. It's made of two words design and pattern. Design refers to the application design which leads into implementation and Pattern is something which is recurring (repeating) in the design/implementation. While working on a project or multiple projects, if you find some kind of design/implementation is repeating, we can say that it's a pattern followed in the application. J2EE design patterns are nothing but most recognized application design patterns across various J2EE applications in the world.
It was my second project (way back in 2002), I learnt about most of the J2EE design patterns. At that time, typical n-tier architecture was being followed in IT industry. When I say typical n-tier I don't mean "n" being 3 or 4 but I mean n being something like 10 or more. It has changed recently and now we are following simplistic design with whole lot of third party frameworks. For example we are not creating facade tier, data layer etc., instead we have started using frameworks like spring and hibernate. Design patterns become more applicable in typical n-tier architecture but it doesn't mean that they can't be applied in simple application design. I am not in favor of adopting several design patterns in the application but I would prefer that any selection of design patters are critically reviewed against its suitability in the application design.
Here is what I think about different design patterns and possible suitable uses of them.
1. Model-View-Controller (MVC) Design Pattern: Once we start following OOAD principles, the very first thing we learn in about an object. An object is an entity which has a very clear defined responsibility with lowest possible granularity. If applying the same concept at little broader level, it results into MVC design pattern. Under MVC design patters, we classify our classes in three buckets namely model, view and controller. Model is the category of classes which represent enterprise data with no to minimum logic e.g. data transfer objects. Controller is the category of class(es) which control the navigational logic and initiate the business process e.g. servlet controller. View is the category of classes used in presentation of the enterprise data in form of an information e.g. JSPs.
This is my favorite design pattern with one confusion. If I start categorizing my all classes in above three buckets, I am unable to think a right place for the classes having pure business logic. Therefore for my own ease, I introduced a fourth category called "Business" and named this design pattern as MVCB design pattern. I am totally onboard with this design pattern and can't think of any reason for not using it.
2. Factory Design Pattern: As the name suggests, it's a pattern when we implement a functionality similar to factory. Factory means any factory which produces goods in mass e.g. Toy Factory, Car Factory etc. The idea taken from factory is you pass some instructions to the factory and you get your desired product(obviously if that factory produces it) without much bothering about internal steps taken within the factory. Similarly in J2EE world, a factory class has responsibility to create different objects based on certain inputs. I think this was/is the most popular J2EE pattern in a typical n-tier architecture. This was mostly being used in instantiating Value Objects or Command objects based on certain parameters.
I am not against using this design pattern but I don't suggest to use it for above said purpose e.g. for creating value objects or command objects. There is no value in instantiating a value object or command object or any other similar object without having complex logic involved in creation of the object itself through factory, instead we can simply call the required class constructor. We should use a Factory only when we have complex/average logic involved in creation of the object itself e.g. database connection session object creation. To create a session object, we need to pass all different arguments, perform data source lookup (as applicable) etc. In this scenario, I am on to create a session factory (follow factory design pattern).
3. Facade Design Pattern: Facade design pattern is a pattern when you have complex business objects involvement in processing a single request. It becomes messier and less maintainable if you expose all business objects to the requesting body. This also results into more network traffic if you are using Service Oriented Architecture (SOA). Instead of exposing all business objects to the client component, you can create a wrapper implementation involving all required business objects and give handle of this wrapper object to the requesting body (client). This wrapper implementation is nothing but a facade to make the business processing requests and this design pattern is called Facade design pattern.
As mentioned above, this pattern is more applicable when you are having complex involvement of business objects in individual business request processing. Its becomes more applicable when this kind of behavior is implemented using Service Oriented Architecture (SOA). This was again a very popular pattern in typical n-tier applications specially implemented using EJBs. I find rare scenarios in recent applications where Facade design pattern becomes applicable.
4. Singleton Design pattern: Singleton design pattern is all about restricting the number of instances of a particular class in the application. This is done by hiding the class constructor and exposing some static method which either exposes the only instance of the class or performs required operations on the single instance of the class.
Typical candidate for Singleton design pattern is connection factory class where you would not want to instantiate multiple instances of the factory class and rather you would like to use the single instance of the class throughout the application. If I look at the recent trend, I find that with the introduction of frameworks like Spring, this design pattern is not being used explicitly. This becomes silent pattern in the application automatically.
5. Visitor Design Pattern: Again as the name suggests, visitor design pattern is all about traversing an object graph. If your application uses object with multiple depth involving collection of objects at any level, you end up writing logic to traverse through the object graph including every object irrespective of its level for its processing. If you generalize the concept irrespective of the underlying objects, it becomes Visitor Design Pattern.
This design pattern becomes very useful in dealing with big object graphs with no available traversing mechanism. With introduction of aspects, we are able to insert processing logic at method call levels staying out of the object. There are also some other frameworks available which enable you to take your processing logic from the object graph level e.g. to persist a database object along with its dependent collections, we can think of using visitor design pattern. But before going for it, I would evaluate uses of any good ORM such as Hibernate, Toplink, BC4J which takes care of my requirement altogether. I would go for visitor design pattern only when I have applicable scenario and also I need to write my processing logic explicitly.
There are some more design patterns followed rarely now a days. I would not like to go in much detail of them. Below is the list of some of them.
1. Service Locator Design Pattern: This is a design pattern where we create classes with responsibility to locate my service classes. This used to be/is very useful in case of application using EJBs. In such applications, we can create EJBLocators which will perform the lookup and return the EJB handle. In normal enterprise application, I am not inclined to use this design pattern as there is no to rare use left for it now a days.
2. Command Design Pattern: Under this design pattern, we introduce and extra layers called command layers. This layers behaves as a glue between requesting object (client) and service processing object(business object). Other than extra decoupling of business logic with client/presentation logic, I don't see any advantage from using it. Until my business calls are very complex and intrusive, I will not go for this design pattern anymore.
3. Delegate Design Pattern: Under this design pattern, we create classes with only responsibility to delegate to requests from one class(layer) to other class(layer). Since delegates don't carry out any extra value, I am not inclined to use this design pattern anymore.
4. Helper Design Pattern: Under this pattern, we takeout part of the processing logic from the main class and put in a secondary class called Helper. Helper classes are very similar but may use some system, business objects as opposed to the Util classes e.g. we can create StrutsActionHelper class to supplement struts action logic. Only difference between a typical Util class and this helper is that this helper can use all struts framework objects while its not advised for the Util class.
5. Data Access Object (DAO) Design Pattern: Under this pattern, we typically write a call having responsibility to initiate any database calls. As mentioned earlier, I am on to use ORM than implementing a DAO.