02: Scenarios based Java OO concepts & GoF design patterns – naive Template Method pattern

Extends Can you design classes & interfaces using OO?. Only experience, and asking the right questions can teach you what design pattern to use, in which scenario.

Scenario: A company named XYZ Retail is in the business of selling Books, CDs and Cosmetics. Books are sales tax exempt and CDs and Cosmetics have a sales tax of 10%. CDs can be imported and attracts an import tax of 5%. Write a simple shopping basket program, which will calculate extended price (qty * (unitprice + tax)) inclusive of tax for each item in the basket?

Solution: Sample code for the items (i.e. Goods sold by XYZ Retail). Let’s define an Item interface to follow the design principle of code to an interface not to an implementation.

Covers coding to interface or abstract classes, inheritance, composition, and how to create a class with single responsibility and then collaborate & reuse behavior via inheritance & composition.

Let’s start with a naive solution, and improve the design in the ensuing series of posts.

Class Diagram

Both inheritance & composition gives you code reuse.

Class Diagram showing interface inheritance, implementation inheritance & composition

Class Diagram showing interface inheritance, implementation inheritance & composition

Step 1: The “Item” interface that defines the methods to be implemented by the “Goods” class.

Step 2: The “Goods” class is abstract as it implements the common behavior of Book, CD, and Cosmetics, and implements the interface “Item”. It composes (i.e composition) “TaxCalculator” to perform the tax calculation.

Step 3: The TaxCalculator interface & the implementation TaxCalculatorImpl.

Step 4: Now, the specific Goods like Book, CD, and Cosmetics that extends the shared behavior. In other words, inherits the shared behavior of Goods. The isTaxable & isImportedare specific to the product. New products can be added in the future with specific taxable & importable behaviors.

Step 5: Finally, a simple main class to run the code.


Key Points to observe

  • In Java 8, you can have default method implementations in an interface, but you cannot store state (e.g.price, qty, etc).
  • The shared or common behavior is encapsulated in the “Goods” abstract class, which cannot be instantiated. It applies the template method design pattern by having 2 abstract methods “isTaxed()” and “isImported()” in the Goods class to be extended by the sub classes like Book, CD, etc to provide the specific implementations. The “Template Method” & “Composite” design patterns make use of implementation inheritance.
  • The Book, CD, and Cosmetics inherit the behavior from the parent class “Goods” for extended tax and extended price.
  • The TaxCalculator is composed as a helper method within “Goods” to calculate the tax based on a specific item’s “isTaxed()” & “isImported()” behaviors.
  • Each class is given a single responsibility, which is a design principle. TaxCaluculator is for calculating the tax, Goods class is for capturing the state & calculating the extended tax & price and the product specific classes like Book, CD, etc for defining the default product specific “isTaxed()” and “isImported()” behaviors & a setImported(boolean imported) method to override default value of “false” as CDs can be imported.

What is wrong with the above design?

  • Do we really need the “Item” interface? Can we get away with the abstract “Goods” class?
  • When you have 3 items to sell it is okay to create its own class like Book, CD, and Cosmetics. But, what if when you sell 100+ products in the future? It will not be a good idea to create individual classes for each item or goods. So, how can we use abstraction to get a more flexible design?
  • If we apply abstraction and capture the item type as an attribute named “type” to represent Book, CD, Cosmetics, etc within the “Goods” class, you may run into unsightly if/else statements as shown below, which makes your code rigid & hard to maintain or extend.

Let’s build on this in the next post to address the above design concerns => 03: Scenarios based Java OO design & GoF design patterns – Strategy Pattern

800+ Java Interview Q&As Menu

Learn by categories on the go...
Learn by categories such as FAQs – Core Java, Key Area – Low Latency, Core Java – Java 8, JEE – Microservices, Big Data – NoSQL, Architecture – Distributed, Big Data – Spark, etc. Some posts belong to multiple categories.