Applying Java Design Patterns
After analyzing the nature of validation business requirements in this article's example, it's obvious that the ideal patterns to simplify the validation process are: strategy,factory, and singleton.
Design Pattern: Strategy
Here's the strategy design pattern's official definition:
"The strategy design pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it."
If you implement the IdentityValidationStrategy interface and overwrite any common validation in any identity number validation, the strategy design pattern will help you maintain the correct behaviors in the business requirements.
This is because different identity types might have completely different validation rule definitions. For instance, an ABC PIN number might not only validate its minimum length and its maximum length, but also its format mask pattern. On the other hand, a birth certificate number might need only to validate its minimum length without a mask pattern match due to its completely different format style in different countries. Theoretically, it is possible to add other constraints to the birth certificate number validation-for instance,the country code restriction. Therefore, it's easier to add any sub-validation rule to the specific identity validation.
Later on, if the business requirements for the identity validation rule change, you'll only need to apply the implementation changes to the relevant identities' strategy implementations. You can easily add or remove one more identity type validation from your application. For example, just createa new type of IdentityValidationStrategy called CreditCardNumber and its constructor with the following code:
public CreditCardNumber() {
super(TYPE_CREDIT_CART_NUMBER, CONFIG_ CREDIT_CARD_NUMBER);
}
Then add its validation rule into the personalIdentity.xml file. You won't need to modify the existing code or only re-factor with the minimum changes.
This design solution also meets one of the OO Principles: "Classes should be open for extension, but closed for modification."
Loosely Coupled Design and the HAS-A Can Be Better than IS-A Principle
"Strive for Loosely coupled designs between objects that interact" is an important OO principle. In this example, that means you have to design and create an identity validation XML configuration file (personalIdentity.xml) to contain all of the validation strategy rules for each individual identity type. personalIdentity.xml is shown in Listing 7.
All of these validation rules and their corresponding message keys for each identity are configurable. If you have any changes to them, no code change is necessary.
Another design principle counsels you to "Favor composition over inheritance." If you are creating the system, using the composition gives you a lot more flexibility. You can change the object behavior at runtime as long as the object you work with implements the correct behavior interface. Since the identity validation strategy is defined in the XML format, you'll need to find the proper Java XML parser and include it in the application.
There are several ways to parse personalIdentity.xml so it creates the Java object which retrieves each identity's validation rule in the runtime. Two basic methods parse XML documents:
- The Document Object Model (DOM) Method: When parsing an XML document with DOM, the parser reads the entire document and creates a tree-like representation of it. The DOM method is sometimes easier to implement, but it's slower and more resource-intensive than the other alternative.
- Using SAX: SAX parses XML documents with events.
This example uses Apache Jakarta Digester, which simplifies SAX parsing by providing a higher-level interface to SAX events. This interface hides much of the complexity involved in XML document navigation, allowing developers to concentrate on processing XML data instead of parsing it.
Digester was initially developed to simplify XML-configuration file parsing, but it also is useful whenever you need to map XML files to Java objects. It has the following advanced features:
- Ability to plug in your own pattern matching engine, if the standard one is not sufficient for your requirements.
- Optional namespace-aware processing, so that you can define rules that are relevant only to a particular XML namespace.
- Encapsulation of Rules into RuleSets that can be easily and conveniently reused in more than one application that requires the same type of processing.
The IdentityValidationStrategyParser class has been created to include the abilities:
- Parse identity validation XML configuration file by using the
org.apache.commons.digester.Digester class.
- Create each identity validation strategy object by using the
IdentityValidationStrategyFactory class.
Design Pattern: Factory
You've already implemented two factory classes, IdentityValidationStrategyFactory and IdentityValidationActionMessageFactory. These create the individual IdentityValidationStrategy for each identity type and its corresponding action error message with the proper error message key to each validation rule.
For example, if the customer selects the DRIVER LICENSE identity type, this creates a DriverLicenseNumber instance new DriverLicenseNumber(). This instance will be populated by the following method, defined in the IdentityValidationStrategyFactory class:
populateIdentityStrategy( IdentityValidationStrategy strategy, String identityName, String
identityType, String minimumLength, String maximumLength, String mask, String
minLengthErrorMessageKey, String maxLengthErrorMessageKey, String maskErrorMessageKey, String
defaultErrorMessageKey)
When the actual validation rule fails in the customized, Struts-pluggable IdentityValidator, the corresponding validation error message is created through the following method:
createActionMessage(
IdentityValidationStrategy validateStrategy, String identityField,
String validationRule,
ValidatorAction validatorAction,
Field field, HttpServletRequest request)
defined in the IdentityValidationActionMessageFactory class
This application has adopted the Simple Factory pattern. While it may not actually be a design pattern, it IS a commonly used programming idiom.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.