Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Generic Types with Dynamic Decorators

JavaFAQ Home » Story by Dr. Kabutz Go to all tips in Story by Dr. Kabutz


Bookmark and Share

The Java Specialists' Newsletter [Issue 034] - Generic Types with Dynamic Decorators

Author: Dr. Heinz M. Kabutz

JDK version:

Category: Language

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

Welcome to the 34th issue of "The Java(tm) Specialists' Newsletter", in which we look at how we can apply the dynamic decorators to produce type-safe iterators dynamically. I know that some of you will be tempted to write to me how "that will all be in JDK 1.5" or "here are 1001 reasons why your construct is not useful". The purpose of this newsletter is to make you think, please don't forget that. It is not to provide you with cut & dry solutions to your problems.

Thanks to Dr. Christoph Jung and Bruce Eckel for the ideas that spawned this newsletter. Some of these examples will probably be featured in the "Thinking in Patterns" book that Bruce is busy writing at the moment. I can't wait for that to get published ...

How do you go from being an OO beginner to an OO guru? Simple answer: Experience! But what if you can't wait 10 years to get that experience? Simple answer: Design Patterns! How can you learn Design Patterns in a relaxed setting from someone who has used them in the real world? Simple answer: Ask about my new course "Design Patterns - The Timeless Way of Coding".

1486 members are currently subscribed from 55 countries

Proxy vs. Decorator

What is the difference between a Proxy and a Decorator?

If we look at the structure of these patterns in the GoF book, we see that the Proxy has an association from the Proxy class to the RealSubject class (actually, it would be more versatile to have an association between Proxy and the Subject interface). Essentially the structure in Java code would look like this:

interface Subject {
  public void request();
}

class RealSubject implements Subject {
  public void request() { /* do something */ }
}

class Proxy implements Subject {
  private Subject realSubject;
  Proxy(Subject realSubject) {
    this.realSubject = realSubject;
  }
  public void request() {
    /* do something, then */
    realSubject.request();
  }
}

The Decorator pattern's structure has an aggregation from the Decorator class to the Component. The structure in Java code would look like this:

interface Component {
  public void operation();
}

class ConcreteComponent implements Component {
  public void operation() {
    /* do something */
  }
}

class Decorator implements Subject {
  private Component component;
  Decorator(Component component) {
    this.component = component;
  }
  public void operation() {
    /* do something, then */
    component.operation();
  }
}

class ConcreteDecorator extends Decorator {
  ConcreteDecorator(Component component) {
    super(component);
  }
  public void anotherOperation() {
    /* decorate the other operation in some way, then call the
     other operation() */
    operation();
  }
}

If we now change the names of the classes to A, B, C and the method to f(), Proxy becomes:

interface A {
  public void f();
}

class B implements A {
  public void f() { /* do something */ }
}

class C implements A {
  private A a;
  C(A a) {
    this.a = a;
  }
  public void f() {
    /* do something, then */
    a.f();
  }
}

And if we do the same to Decorator, that becomes:

interface A {
  public void f();
}

class B implements A{
  public void f() { /* do something */ }
}

class C implements A {
  private A a;
  C(A a) {
    this.a = a;
  }
  public void f() {
    /* do something, then */
    a.f();
  }
}

class D extends C {
  D(A a) {
    super(a);
  }
  public void g() {
    /* decorate the other operation in some way, then call the
     other operation() */
    f();
  }
}

Oops, by looking at the structure alone, we see that there is not that much difference between Proxy and Decorator. We also have to look at the intents:

Proxy: Provide a surrogate or placeholder for another object to control access to it.

Decorator: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

We have to look at the structure and the intent and the applicability together if we want to figure out which pattern we are looking at. Even then, since a lot of the patterns are very similar, we can get into heated debates about this. Bruce Eckel and I exchanged some interesting emails trying to decide whether what you are about to see is the Decorator, Adapter or Proxy.

If you got lost in this discussion, you are missing out on one of the most powerful techniques developed in Software Engineering in the last decade, that being Design Patterns. I've developed a new classroom-based course that will teach you how to recognise and apply Object-Oriented Design Patterns. Please send me an email if you would like to know more.

The answer to the question of "what is the difference between a Proxy and a Decorator" lies mainly in the intent. We intend to use a Decorator to extend the interface of a object dynamically, whereas a Proxy is intended to provide a surrogate object for the real object.

Enough of a Design Patterns lesson. Let's get to the meat of today's newsletter.

Generic Types with Dynamic Decorators

Bruce Eckel sent me an email asking if I had some nice examples for using the Dynamic Proxies of JDK 1.3. I passed the question on to my friend Christoph Jung who sent an interesting reply. He said that they use dynamic proxies quite a lot in order to handle type-safe collections. The issues addressed actually reminded me of generic collections, due in JDK 1.5 hopefully.

Let's remember how we used collections in the past. Say we had a stray animal pound in which we had collections of dogs and cats. This code is what the "client" code of our dogs and cats would use, i.e. in the client code we have to keep on doing type casting down to the correct type while iterating through the collection.

public class Cat {
  private final String species;
  public Cat(String species) { this.species = species; }
  public String toString() { return species; }
  public void meow() { System.out.println(this + ": Meow"); }
}

public class Dog {
  private final String species;
  public Dog(String species) { this.species = species; }
  public String toString() { return species; }
  public void bark() { System.out.println(this + ": Woof"); }
}

import java.util.*;
public class Pound {
  private Collection dogs;
  private Collection cats;
  public Pound(Dog[] dogs, Cat[] cats) {
    this.dogs = Arrays.asList(dogs);
    this.cats = Arrays.asList(cats);
  }
  public void makeNoise() {
    Iterator dog_it = dogs.iterator();
    while(dog_it.hasNext()) {
      ((Dog)dog_it.next()).bark(); // we have to downcast!
    }
    Iterator cat_it = cats.iterator();
    while(cat_it.hasNext()) {
      ((Cat)cat_it.next()).meow(); // we have to downcast!
    }
  }
}

Wouldn't it be nice if we could have a collection for dogs and a collection for cats so that we would not have to worry about downcasting? Indeed, but Java does not support generics yet, I hear some of you say.

How could we improve our situation by abusing dynamic proxies? (For a detailed newsletter on dynamic proxies, please refer to http://www.smotricz.com/kabutz/Issue005.html) What if we decided on a naming convention within our objects that we want to collect? Let's say we change Dog to be the following:

public class Dog {
  private final String species;
  public Dog(String species) { this.species = species; }
  public String toString() { return species; }
  public void bark() { System.out.println(this + ": Woof"); }
  public static interface Collection extends java.util.Collection {
    Iterator dogIterator();
  }
  public static interface Iterator extends java.util.Iterator {
    Dog nextDog();
  }
}
}

Our client code could therefore use Dog.Collection and call method dogIterator(), which would return a Dog.Iterator with the specialised method nextDog(). This means we never have to downcast the anonymous objects to Dog!

So, how do we actually make an instance of this Dog.Collection? Simple, dynamic proxies ... with a twist. First of all, I write a GenericFactory class (the Fowler Factory Method pattern, not the GoF). This GenericFactory has a makeCollection() method where I pass in an instance of the collection backing the Dog.Collection (this is where the adapter pattern comes in), and the type that I want to support. It is assumed that the type you pass in (e.g. Dog.class) has an inner interface called Collection with a method dogIterator() and another inner interface called Iterator that contains a method nextDog(). If these are not found we throw an IllegalArgumentException.

import java.lang.reflect.Proxy;
import java.util.*;
public class GenericFactory {
  public static Collection makeCollection(Collection backing,
      Class type) {
    GenericCollection gen = new GenericCollection(backing, type);
    return (Collection)Proxy.newProxyInstance(
      gen.getTypeCollectionClass().getClassLoader(),
      new Class[] { gen.getTypeCollectionClass() },
      gen);
  }
  /* please ignore makeIterator for now ... */
  public static Iterator makeIterator(Iterator backing, Class type) {
    GenericIterator gen = new GenericIterator(backing, type);
    return (Iterator)Proxy.newProxyInstance(
      gen.getTypeIteratorClass().getClassLoader(),
      new Class[] { gen.getTypeIteratorClass() },
      gen);
  }
}

The GenericCollection class looks something like this. What it does is intercept any calls to the Dog.Collection proxy and checks if it is the dogIterator() method. If it is, it uses the GenericFactory to make a Dog.Iterator.

import java.lang.reflect.*;
import java.util.*;
public class GenericCollection implements InvocationHandler {
  private final Collection backing;
  private final Class type;
  private final Class typeCollection;

  public GenericCollection(Collection backing, Class type) {
    this.backing = backing;
    this.type = type;
    typeCollection = discoverCollection();
  }

  /** Find the correct inner class Collection interface.
    @throws IllegalArgumentException if inner interface Collection
    not found */
  private Class discoverCollection() {
    Class[] innerClasses = type.getClasses();
    for (int i=0; iif (innerClasses[i].getName().equals(
          type.getName() + "$Collection")) {
        return innerClasses[i];
      }
    }
    throw new IllegalArgumentException(
      "Class does not contain inner Collection interface");
  }

  public Class getTypeCollectionClass() {
    return typeCollection;
  }

  /** This is the meat of the GenericCollection.  It finds any
    method with type name followed by iterator and hijacks it. */
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    if (method.getName().equalsIgnoreCase(type.getName() + "Iterator")) {
      return GenericFactory.makeIterator(backing.iterator(), type);
    }
    return method.invoke(backing, args);
  }
}

In order to make the picture complete, we also have to see the code that makes the Iterators. The GenericIterator looks very similar to the GenericCollection. I am sure we could have a GenericType from which both of those classes could inherit and which could contain common functionality. However, I was writing the code while trying to pacify a crying baby. Not that easy, seeing that I cleverly changed all the keys around on my notebook so that now the only way to use it is to touchtype. Almost dropped it a few times - the notebook, that is Wink

import java.lang.reflect.*;
import java.util.*;

public class GenericIterator implements InvocationHandler {
  private final Iterator backing;
  private final Class type;
  private final Class typeIterator;

  public GenericIterator(Iterator backing, Class type) {
    this.backing = backing;
    this.type = type;
    typeIterator = discoverIterator();
  }

  /** Find the correct inner class Iterator interface.
    @throws IllegalArgumentException if inner interface Iterator
    not found */
  private Class discoverIterator() {
    Class[] innerClasses = type.getClasses();
    for (int i=0; iif (innerClasses[i].getName().equals(
          type.getName() + "$Iterator")) {
        return innerClasses[i];
      }
    }
    throw new IllegalArgumentException(
      "Class does not contain inner Iterator interface");
  }

  public Class getTypeIteratorClass() {
    return typeIterator;
  }

  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    if (method.getName().equalsIgnoreCase("next" + type.getName())) {
      return backing.next();
    }
    return method.invoke(backing, args);
  }
}

How do you use this code? Let's have another look at the newly improved Pound class. You will notice that I am making the collections in the constructor of the Pound, and after that I use those collections directly. Normally, the collections would contain Value Objects from your database, and they would be made dynamically by your framework.

import java.util.*;
public class Pound {
  private Dog.Collection dogs;
  private Cat.Collection cats;
  public Pound(Dog[] dogs, Cat[] cats) {
    this.dogs = (Dog.Collection)GenericFactory.makeCollection(
      new LinkedList(Arrays.asList(dogs)), Dog.class);
    this.cats = (Cat.Collection)GenericFactory.makeCollection(
      new ArrayList(Arrays.asList(cats)), Cat.class);
  }
  public void makeNoise() {
    Dog.Iterator dog_it = dogs.dogIterator();
    while(dog_it.hasNext()) {
      /* no more downcasting! */
      dog_it.nextDog().bark();
    }
    Cat.Iterator cat_it = cats.catIterator();
    while(cat_it.hasNext()) {
      /* no more downcasting! */
      cat_it.nextCat().meow();
    }
  }
}
}

We can test that in our PoundTest class by making a new Pound and calling the makeNoise method.

public class PoundTest {
  public static void main(String[] clargs) throws ClassNotFoundException {
    Pound spca = new Pound(
      new Dog[] {
        new Dog("Alsation"),
        new Dog("Bulldog"),
        new Dog("PavementSpecial") },
      new Cat[] {
        new Cat("RussianBlue"),
        new Cat("DeadBounce") });
    spca.makeNoise();
  }
}

With output of:

Alsation: Woof
Bulldog: Woof
PavementSpecial: Woof
RussianBlue: Meow
DeadBounce: Meow

Oh, by the way, Cat would look like this:

public class Cat {
  private final String species;
  public Cat(String species) { this.species = species; }
  public String toString() { return species; }
  public void meow() { System.out.println(this + ": Meow"); }
  public static interface Collection extends java.util.Collection {
    Iterator catIterator();
  }
  public static interface Iterator extends java.util.Iterator {
    Cat nextCat();
  }
}

Yes, I know this is only a small step towards all the things you can do with generics in C++, and hopefully in JDK 1.5. However, it has made me think in a different way about what we can do with dynamic "proxies".

Was that a Proxy or a Decorator?

Back to our earlier discussion of whether this was a Proxy or a Decorator. I say this is more of a Decorator than anything else, as we are dynamically and transparently extending the functionality of existing classes without subtyping. The interesting part is that the Decorator class is not actually a class per se, it is a naming convention.

Disclaimer

I know that the dynamic decorators shown in this newsletters have some deficiencies at the moment. For example, it is possible to add a Cat to a collection of Dogs without an exception being thrown immediately. In a production-quality system you should obviously check that. throw new ExerciseForTheReaderException();

Last Words

Yes, I know that I am harping on about Design Patterns. However, without a solid understanding of Design Patterns you will never be a real Java Specialist. So, don't delay, pop me an email today ... Smile


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

 Printer Friendly Page  Printer Friendly Page
 Send to a Friend  Send to a Friend

.. Bookmark and Share

Search here again if you need more info!
Custom Search



Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy