Design Patterns
Typical uses for design patterns
Visitor Pattern for User Interface and Display

I was browsing the NHibernate forums and came across a post by "thatmikewilliams" who posted the following code:

--------------------------------------------------------

Because this functionality is closely tied to the user interface you should probably use a visitor for this (rather than an overridden method in your class hierarchy).

package test.visitor;
public abstract class Payment {
   interface Visitor {
      Object visit(CardPayment payment);
      Object visit(CashPayment payment);
   }
   public abstract Object accept(Visitor visitor);
}

package test.visitor;
public class CardPayment extends Payment {
   @Override
   public Object accept(Visitor visitor) {
      return visitor.visit(this);
   }
}

package test.visitor;
public class CashPayment extends Payment {
   @Override
   public Object accept(Visitor visitor) {
      return visitor.visit(this);
   }
}

package test.visitor;
public class PaymentDisplayStringVisitor implements Payment.Visitor {
   public Object visit(CardPayment payment) {
      return "CC";
   }
   public Object visit(CashPayment payment) {
      return "CS";
   }
}

package test.visitor;
import java.util.ArrayList;
import java.util.List;
public class Test {

   public static void main(String[] args) {
      List<Payment> payments = new ArrayList<Payment>();
      payments.add(new CashPayment());
      payments.add(new CardPayment());
      
      PaymentDisplayStringVisitor visitor = new PaymentDisplayStringVisitor();
      for (Payment payment : payments) {
         System.out.println(payment.accept(visitor));
      }
   }
}

----------------------------------------------

Using the Visitor Pattern to display domain specific types on a user interface is a nice approach instead of overriding specific methods on your domain object, on top of that, cluttering your domain objects with useless "UI" specific methods like ("get object name").  Pretty interesting approach. :)  Notice the PaymentDisplayStringVisitor returns specific string type based on the type.  Very Cool.  I'll try extending this approach using .NET and Generics and post some code later.

The Strategy Design Pattern

Today, I'm going to write about the strategy design pattern and give some examples on where it should be used and why it's useful. I'm really sleepy, only had 3 hours of sleep, so I hope I can do this quick and off the top of my head.

       

The Problem and Design Smell

Suppose we have the following class hierarchy:

We have an abstract Animal class, that has two virtual methods Eat() and MakeNoise(). Both household Cat and household Dog classes inherit from Animal, along with inheriting behavior animal behavior. Inheriting behavior typically leads to bad design and maintainability. Let's look at the code implementing the classes:

When we run these classes, we get the following output:

The problem ('design smell') associated with this approach is simply the way we are placing the implementation of the actions Eat() and MakeNoise() inside the concrete classes. This doesn't exactly lead to a maintainable design. For example, suppose we want to extend our animal kingdom by introducing an AllyCat class. An AllyCat might have different implementations of Eat() (eating out of the trash), but still have the same kind of MakeNoise() (moew) implementation. You might think, "well, we can just derive from the concrete class Cat, and override the Eat() method with our own AllyCat.Eat() implementation" and you're right, you can. However, extending behavior through hierarchal inheritance should be avoided. Not only that, designs like this can lead to duplicate code.

 

Instead, you should compose classes with isolated algorithm implementations. The goal is to separate varying-code from non-varying code. A quick way to identify non-varying code aspects of your classes is through "has-a" relationships. A Dog "has-a" distinct eating behavior, a Cat "has-a" distinct eating behavior, an AllyCat "has-a" distinct eating behavior, so on and so forth... From our classes and implementation, we have noise behaviors and eating behaviors.

     

The Solution

The solution to basic problems is to implement a Strategy pattern. Consider the following architecture:

And taking a peek in some of the Cat, Ally Cat and Dog code:

 

 

 

All that we have done with this new architecture is delegate the "making noise" and "eating" to behavioral classes that specifically handle the task. We have delegated control to the behavioral classes. This is a much better extensible and coherent design and often leads itself to better to code reuse.

 

Whenever we create classes that are composed of behavioral actions, we call these compositions. Classes such as Dog, Cat, and AllyCat are compositions of behaviors and gain their behavior through composition, not inheritance. Inheritance (like the previous architecture) can lead to unintended consequences when fiddling with the superclass and is more prone to breaking existing code.

     

Common Uses

  1. Algorithm Families – A general case different algorithms need to run depending on a particular situation.
  2. Sorting - Used in sorting when different types of sort algorithms need to be applied to a collection. For example, List.SortBy(FirstNameStrategy)
  3. Behavioral – Used when many distinct "behaviors" are expected of derived classes.

     

Naming Keywords for the pattern

When naming your interfaces, here are some keywords to include in the naming of your strategy

  • General: Strategy, Algorithm
    • Example: CaliforniaTaxStrategy
  • Behavioral: Behavior, Action, Style
    • Example: BarkBehavior

     

Principals to take away from this strategy

  • Look at your application, and analyze the classes that are producing the Design Smell. Take those classes, and analyze the functionality of the classes that are producing this type of Design Smell. Create a separation of varying code and non-varying code (such as specific behaviors that tend to stay the same across all classes or with every new requirement). Once you've identified the non-varying code, then you have an opportunity to extract the behavior from the class and isolate it in its own behavioral family.
  • Use composition rather than inheritance. Composition is encapsulating several behavior/strategies in one class to perform its work. Classes should not inherit their behaviors from base classes; instead they should be composed of behaviors/strategies.
  • Has-A relationships are good indicators that strategy pattern can be used.

         

Formal definition of the strategy pattern

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

     

This blog post is a little dry because I'm really sleepy, I'll try updating it to make it a little more clear later when I have more time. But I hope some of you understand! Later I'll show you how to improve this architecture.

2 Comments Filed Under [ Design Patterns ]
Design Toolbox

Here's a quick summary of Design Guidelines for your Design Toolbox.

Object Oriented Basics

  • Abstraction
  • Encapsulation
  • Polymorphism
  • Inheritance

           

Object Oriented Principals

  • Encapsulate what varies (think strategy pattern)
  • Favor composition over inheritance
  • Program to interfaces not implementations

           

Object Oriented Patterns

  • Strategy – Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm very independently form clients that use it.
  • Observer – Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  • Decorator – Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sublcassing for extending functionality.
  • Factory Method Pattern – Defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. Creates objects through inheritance.
  • Abstract Factory Pattern – Provides an interface for creating families of related or dependent objects without specifying their concrete classes. Creates objects through composition.

           

General Design Principals

  • Identify the aspects of your application that very and separate them from what stays the same.
  • Program to an interface, not an implementation.
  • Favor composition over inheritance.
  • Strive for loosely coupled designs between objects.
  • Classes should be open for extension, but closed for modification.
  • Depend on abstractions. Do not depend upon concrete classes.
  • Follow the Dependency Inversion Principle Guidelines
    • No variable should hold a reference to a concrete class.
      • If you use new, you'll be holding a reference to a concrete class, use factories.
    • No class should derive from a concrete class.
      • If you derive from a concrete class, you're depending on a concrete class, derive from abstractions.
    • No method should override an implemented method of any of its base classes.
      • If you override an implemented method, then your basee class wasn't really an abstraction to start with. Methods defined in your base class were meant to be shared by all subclasses.

     

     

Add Comment Filed Under [ Design Patterns ]