Java IoT Authors: Pat Romanski, Elizabeth White, Liz McMillan, Yeshim Deniz, Mehdi Daoudi

Related Topics: Java IoT

Java IoT: Article

Design Patterns

Design Patterns

Design Patterns are blueprints that describe how to design class structures and object interactions to solve commonly encountered problems. A Design Pattern can be as simple as the practice of using an interface to achieve polymorphism and as complicated as designs used to solve intricate concurrency problems.

If you are a Java developer then you have certainly used Design Patterns in your development efforts in the past. This is an inescapable truth because the Java language itself and all of its associated APIs are designed to leverage some of the most common design patterns known. For example: the java.awt package utilizes the Strategy Pattern in choosing layout managers; the java.io package uses the Decorator Wrapper pattern and the java.sql package, commonly known as JDBC, leverages the Abstract Factory Pattern.

Design Patterns are simply a way of doing things. Every time you prepare to design a system you continually ask yourself, "OK, here is the problem, what is the solution?" All too often, engineers focus on the specific problem at hand without regard to future needs. This results in applications that are difficult to change and extend. Design Patterns can help you avoid this problem by providing you with a road map of how to structure your classes and their interactions to be as flexible and extensible as possible.

This article will demonstrate the power of a few Design Patterns by revealing them in commonly utilized Java APIs like the AWT and JDBC. Once you understand how easy it is to learn and use Design Patterns, a whole new awareness of OO development will open up for you. This is going to be a religious experience, so be prepared to laugh, cry and pound your computer keyboard in anger as you discover the power of Design Patterns!

The Strategy Pattern
One of the first things you do when learning the Java language is use a layout manager in an applet. Remember the layout managers? FlowLayout, CardLayout, GridLayout, even the impossible to use GridBagLayout. A layout manager is usually used in an applet in the following manner:

public void init( ){
this.setLayout(new FlowLayout());
add( new Button("OK"));
add( new Button("Cancel"));

If you have used a layout manager, then congratulations! You have already implemented the Strategy Pattern. The Strategy Pattern is a design pattern that allows the developer to easily swap different strategies that change how a system behaves without having to change the system's architecture. If, for example, you decided that you wanted to use a BorderLayout instead of a FlowLayout it would be a simple matter of swapping the FlowLayout constructor above with a BorderLayout's. Actually, the layout manager system also requires you to change the add(..) methods slightly depending on which layout is used, but direct interaction between the layout and the Applet (Container) does not change.

You can also use the Strategy Pattern in applications you design. When it is possible to have several different algorithms for performing a process, each of which is the best solution depending on the situation, then a Strategy Pattern may be in order. A Strategy Pattern has three important participants: Strategy, Concrete- Strategy and Context.

Strategy Participant
The Strategy Participant usually will be in the form of a Java interface or abstract class that is general enough so that all of the different types of algorithms you will need can effectively implement it. In most cases, this is a no-brainer because algorithms that serve a similar purpose usually require the same method calls. In the AWT layout manager system, the Strategy participant is the java.awt.LayoutManager interface. The LayoutManager interface defines a set of methods that any layout, regardless of how it functions, would need to implement in order to effectively interact with the Applet. This includes methods to add new components, remove components, re-align components when the Applet is reshaped and so on.

ConcreteStrategy Participant
The ConcreteStrategy participants are the actual algorithms programmed into Java classes. By implementing the same Strategy interface, each algorithm becomes a self contained object with exactly the same set of methods as all the others. In the AWTs layout manager system, the different types of layouts - BorderLayout, FlowLayout, etc. - are the ConcreteStrategy participants. Each of these classes represent a different algorithm for laying out visual components. They all implement the same methods for adding and removing and re-aligning components but they execute these methods in their own special way. The result is several different layouts for viewing the same visual widgets.

Context Participant
The Context Participant is the object that utilizes the services of the ConcreteStrategies. Since all of the ConcreteStrategies have the same interface, it eliminates the need to customize the Context for every strategy it may need to use. When we set the layout manager (applet.setLayout(LayoutManager lm)) in an Applet, we do so by passing in an object reference of type LayoutManager. The Applet doesn't know which ConcreteStrategy we passed to it and it shouldn't care. All it knows is, when it needs to add a component it calls lm.addComponent(..) and when it detects that the Applet has been re-sized it calls lm.layoutContainer(..). Regardless of which layout manager actually performs the task the result is the same; a component is successfully added and the layout is rearranged.

The beauty behind the Strategy Pattern is the flexibility it gives your system to change its behavior. The Strategy Pattern can be used to accommodate different searching algorithms in text editors, encryption algorithms in network applications, ray tracing algorithms in 3D graphics and ... well, you get the idea. The sky is the limit. Anytime you have a system where there are several different ways of performing the same task, consider the Strategy Pattern as a possible Design Pattern.

The Decorator Wrapper Pattern
If you have done any Java programming at all, you should be familiar with PrintSteam. When you used the System.out.println(..) in your very first Java program you were, in fact, using a PrintStream object.

("Hello World!");
// System.out is a
PrintStream object

Did you know when you wrote this that you were using the Decorator Wrapper Pattern? Pretty easy isn't it? The Decorator Wrapper Pattern has the general goal of enhancing the functionality of an object by wrapping it in another object. It is the opposite of a Strategy Pattern. Where a Strategy Pattern allows you to swap the underlying object while maintaining the same interface, the Wrapper Pattern allows you to change the interface while maintaining the underlying object. The Decorator Wrapper Pattern provide several advantages, but two of the most important are the ability to apply and withdraw functionality and the ability to dynamically wrap one wrapper inside another to provide different combinations of functionality.

The java.io package is a great example of the Decorator Wrapper Pattern. Let's say you want to write some information to a file using the java.io package. First you need to create an OutputStream to a file:

FileOutputStream fileOut =
new FileOutputStream("super_secret.txt");

A FileOutputStream allows you to write only in the form of bytes to a file by calling its write(byte [ ] b) method. We can make it easier to write our text to the file by wrapping the FileOutputStream in a PrintStream object (see Listing 1).

Wow! That was pretty easy. We took advantage of the Decorator Wrapper Pattern's ability to add new functionality by wrapping our FileOutputStream in a PrintStream to obtain a friendlier interface. Of course, now your super secret information is super easy for anyone to read. What if we could encrypt the text? We would need to add another wrapper to the FileOutputStream. This is easy with the Decorator Wrapper Pattern used in the java.io package.

First, we create a new wrapper that does the encoding. We call it the BitReverserOut. This filter reverses the bit values on every byte so that the first four bits and the last four are reversed. It's not rocket science but it will make the file unreadable (see Listing 2).

Now that we have our new wrapper we can include it in our application to achieve seamless encryption (see Listing 3).

Now that's the Decorator Wrapper Pattern really doing its job! Not only were we able to use the PrintStream as a wrapper to add functionality, but we also used the BitReverserOut and PrintStream together to obtain a new combination of functionality. The Decorator Wrapper Pattern has the additional advantage of limiting the number of subclasses needed. Instead of creating a huge family of OutputStream classes that serve every possible need we can leverage the Decorator Wrapper Pattern's dynamic design to obtain a truly unlimited number of combinations - now that's power! A complete program for writing and reading encrypted messages is included in Listing 4.

The Wrapper Pattern has the following participants: Component, ConcreteComponent, Decorator and ConcreteDecorator.

Component Participant
The Component Participant defines the interface for objects that can be enhanced. In the above example, the Component is the OuputStream. In most cases, the Component will be an abstract class. This is true in our example because the OutputStream is abstract.

ConcreteComponent Participant
ConcreteComponents are objects that extend the Component Participant but are not abstract. These are the objects whose functionality we are attempting to enhance. In our example, the ConcreteComponent was the FileOutputStream.

Decorator Participant
The Decorator Participant is the namesake and key element in the Decorator Wrapper Pattern. It is responsible for maintaining a reference to the Component Participant and defining an interface that matches the Component Participant's interface. In Java, the Decorator will usually be a class that extends the Component class. The java.io.FilterOutputStream is the Decorator in the above example. If you look at the definition of the FilterOutputStream you will notice that it matches the OutputStream method for method, but it also includes a member variable, out, which is its internal reference to the OutputStream it decorates.

ConcreteDecorator Participant
The ConcreteDecorator is the group of objects that can add functionality to the ConcreteComponents. ConcreteDecorator extends the Decorator Participant and overrides the appropriate methods adding the functionality needed. The BitReverserOut is an excellent example of this type of participant. You can see in Listing 2 that the BitReverserOut overrides the FilterOutputStream's write(..) method to reverse the bit values before writing them to the OutputStream. This is classic ConcreteDecorator behavior. The fact that a ConcreteDecorator extends the Decorator which extends the component means that the ConcreteDecorator can also be a ConcreteComponent. This is why we can wrap one ConcreteDecorator inside another. In fact, the number of wrappings is unlimited. This kind of recursive wrapping was nicely demonstrated when we wrapped the BitReverserOut inside the PrintStream class.

You can use the Decorator Wrapper Pattern in your applications. When you design an object that has a rudimentary functionality that could be used in a variety of different situations, consider using the Decorator Wrapper Pattern. You also can use the Decorator Wrapper Pattern to reduce the need for huge hierarchies of classes or to provide the capability to enhance functionality dynamically. Some GUI systems use the Decorator Pattern to provide an unlimited number of widgets with out defining every possible component. This is accomplished by using the Decorator Pattern to add graphical embellishments to widgets. If, for example, TextArea is a widget, you could use the Decorator Wrapper Pattern to embellish it with a snazzy beveled border or a scroll bar. The important thing to remember is that the Decorator Wrapper Pattern allows you to enhance the functionality of a basic service by wrapping it inside of decorators. Decorators can be wrapped recursively (one inside the other), allowing for an unlimited number of combinations and added functionality.

The Abstract Factory Pattern
One of the most popular Enterprise APIs is the java.sql or JDBC API. This powerful collection of interfaces and classes makes it possible to change from one database's implementation to the next by changing only one line of code. The JDBC API is a perfect example of the Abstract Factory Pattern. Listing 5 is an example of the JDBC API in action.

In the Strategy Pattern you learned how to accommodate different algorithms by encapsulating them in classes that implemented the same type of interface. The Abstract Factory Pattern accomplishes the same thing, but on a much grander scale. With the Abstract Factory Pattern you can change the behavior of an entire API or family of related classes.

The Abstract Factory Pattern is a perfect Design Pattern when you need to accommodate different solutions using one uniform family of objects. The key to the Abstract Factory Pattern is how objects are created. In the Abstract Factory Pattern, all the objects in the family are obtained as products from other objects in the family. This hides the creation process from the application and allows the vendor to do all kinds of proprietary things in their code that have no impact on the customer's application.

In the JDBC API, the Statement object is always created from the Connection object. This avoids the need to explicitly create a vendor-specific Statement object by doing something like:

Statement stmt =
new CompanyXStatementObject(dbName, props);

The same holds true for the Connection object, which is produced by the Driver object; the ResultSet object which is produced by the Statement object, and so on. By hiding the creation process, the JDBC API allows you to change the type of Driver used - and possibly the database - without changing massive amounts of code in your application. In fact, you need only change one thing, the type of driver instantiated in the beginning of your program. The Abstract Factory Pattern has the following participants: AbstractFactory, ConcreteFactory, AbstractProduct, ConcreteProduct and Client.

AbstractFactory and AbstractProduct Participants
The AbstractFactory Participant is the most important member of this pattern. Usually implemented as an interface, the AbstractFactory is responsible for defining how to produce the other objects that we need. The AbstractProduct defines how the products produced by the AbstractFactory should look to our application. The AbstractProduct also is usually implemented as an interface in Java and defines a fixed set of methods that can be invoked to produce specific results.

In the JDBC API, most of the interfaces are pulling double duty by acting as both AbstractFactorys and AbstractProducts. The Connection interface is returned by invoking the Driver interface's connect(..) method. So the Driver is the AbstractFactory Participant and the Connection is the AbstractProduct.

Connection cnct = drvr.connect( .. );

The Connection interface defines methods that can be used to manage a database connection. These connection management methods define the AbstractProduct aspect of the Connection interface - a fixed set of methods that can be invoked to produce specific results.

cnct.commit( );
cnct.getWarnings( );
cnct.close( );

The Connection interface, however, also defines itself as an AbstractFactory Participant. The Statement interface is returned by invoking the Connection interface's createStatement( ) method. So the Connection is now acting as an AbstractFactory to produce a Statement which is the AbstractProduct.

Statement stmt = cnct.createStatement( );

The Statement interface, like the Connection interface, is both an AbstractProduct and AbstractFactory participant. As an AbstractProduct the Statement interface defines methods for querying and modifying the database. As an AbstractFactory, the Statement interface produces the ResultSet interface, another AbstractProduct of the JDBC API.

ConcreteFactory and ConcreteProduct Participants
OK, here are the guys that do all the work. The ConcreteFactory and ConcreteProduct participants are the actual objects that implement the interfaces defined by AbstractFactory and AbstractProduct respectively. They define the algorithms and procedures that are actually carried out when a Factory method is invoked. In our JDBC API example we can change ConcreteFactorys by changing the Driver that is instantiated in the beginning of our program. You could, for example, change from CompanyX's driver to CompanyA's driver in the following manner:

// Driver drvr =
// new CompanyXProprietaryDriver( );
Driver drvr =
new CompanyAProretaryDriver( );

Voil‡! You're done. From now on, every time a new product is produced by an AbstractFactory call it will actually be a CompanyA ConcreteProduct that is implementing a JDBC AbstractProduct interface. Listing 6 is a look behind the scenes at the creation of a Statement object (ConcreteProduct) by a Connection object (ConcreteFactory).

Client Participant
The Client participant is the environment that the other participants (AbstractFactory, AbstractProduct, ConcreteFactory, and ConcreteProduct) operate in. The Client Participant may recognize only the Abstract participants and must be indifferent to the Concrete participants. In our JDBC example, the client is the application itself.

The AbstractFactory Pattern is an enormously powerful Design Pattern that can be used to decouple (disconnect or unbind) your applications from specific implementations. The new Java Foundation Classes (JFC) recently announced by JavaSoft will use the AbstractFactory Pattern to allow developers to change the look and feel of their applications from Macintosh, to Windows, to a X-Windows interface on any platform on the fly! Developers will even be able to define their own GUI implementations that can be used in the JFC. You can use the AbstractFactory Pattern yourself to decouple how your application accesses services from how they actually work. Next time you need to implement a family of objects and you know there are, or could be, different implementations of the same set of interfaces, consider the AbstractFactory Pattern as a possible design solution.

While you may not have experienced religious rapture while reading this article you should have gained a healthy appreciation for Design Patterns. Design Patterns provide object-oriented designers and architects with tried and proven techniques for solving difficult design problems. They offer solutions that are flexible, extensible and reusable - the three cornerstones of good object-oriented design. If you are interested in learning more about Design Patterns, consider picking up a copy of Design Patterns: Elements of Reusable Object-Oriented Software. Written by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides - a.k.a. "The Gang of Four" - this Addison-Wesley publication is an excellent resource that contains 23 powerful and important Design Patterns.

More Stories By Richard Monson-Haefel

Richard Monson-Haefel, an award-winning author and technical analyst, owns Richard Monson-Haefel Consulting. Formerly he was VP of Developer Relations at Curl Inc. and before that a Senior Analyst at The Burton Group. He was the lead architect of OpenEJB, an open source EJB container used in Apache Geronimo, a member of the JCP Executive Committee, member of JCP EJB expert groups, and an industry analyst for Burton Group researching enterprise computing, open source, and Rich Internet Application (RIA) development.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

IoT & Smart Cities Stories
There are many examples of disruption in consumer space – Uber disrupting the cab industry, Airbnb disrupting the hospitality industry and so on; but have you wondered who is disrupting support and operations? AISERA helps make businesses and customers successful by offering consumer-like user experience for support and operations. We have built the world’s first AI-driven IT / HR / Cloud / Customer Support and Operations solution.
Codete accelerates their clients growth through technological expertise and experience. Codite team works with organizations to meet the challenges that digitalization presents. Their clients include digital start-ups as well as established enterprises in the IT industry. To stay competitive in a highly innovative IT industry, strong R&D departments and bold spin-off initiatives is a must. Codete Data Science and Software Architects teams help corporate clients to stay up to date with the mod...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
Druva is the global leader in Cloud Data Protection and Management, delivering the industry's first data management-as-a-service solution that aggregates data from endpoints, servers and cloud applications and leverages the public cloud to offer a single pane of glass to enable data protection, governance and intelligence-dramatically increasing the availability and visibility of business critical information, while reducing the risk, cost and complexity of managing and protecting it. Druva's...
BMC has unmatched experience in IT management, supporting 92 of the Forbes Global 100, and earning recognition as an ITSM Gartner Magic Quadrant Leader for five years running. Our solutions offer speed, agility, and efficiency to tackle business challenges in the areas of service management, automation, operations, and the mainframe.
The Jevons Paradox suggests that when technological advances increase efficiency of a resource, it results in an overall increase in consumption. Writing on the increased use of coal as a result of technological improvements, 19th-century economist William Stanley Jevons found that these improvements led to the development of new ways to utilize coal. In his session at 19th Cloud Expo, Mark Thiele, Chief Strategy Officer for Apcera, compared the Jevons Paradox to modern-day enterprise IT, examin...
With 10 simultaneous tracks, keynotes, general sessions and targeted breakout classes, @CloudEXPO and DXWorldEXPO are two of the most important technology events of the year. Since its launch over eight years ago, @CloudEXPO and DXWorldEXPO have presented a rock star faculty as well as showcased hundreds of sponsors and exhibitors! In this blog post, we provide 7 tips on how, as part of our world-class faculty, you can deliver one of the most popular sessions at our events. But before reading...
DSR is a supplier of project management, consultancy services and IT solutions that increase effectiveness of a company's operations in the production sector. The company combines in-depth knowledge of international companies with expert knowledge utilising IT tools that support manufacturing and distribution processes. DSR ensures optimization and integration of internal processes which is necessary for companies to grow rapidly. The rapid growth is possible thanks, to specialized services an...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
Scala Hosting is trusted by 50 000 customers from 120 countries and hosting 700 000+ websites. The company has local presence in the United States and Europe and runs an internal R&D department which focuses on changing the status quo in the web hosting industry. Imagine every website owner running their online business on a fully managed cloud VPS platform at an affordable price that's very close to the price of shared hosting. The efforts of the R&D department in the last 3 years made that pos...