Reflection for Creating Decorators
in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
import java.awt.*; import java.io.*; import java.lang.reflect.*; /** * A partial implementation of an application that can be used to * create a decorator (in the sense of the Decorator Pattern) for * a given class. * * This application uses reflection to create a class that has all of * the methods of the given class with calls to the same method in the * decorated object. * * Notes: * * 1. The current implementation does not consider exceptions. * * 2. The current implementation does not consider parameterized types. * * @author Prof. David Bernstein, James Madison University * @version 0.1 */ public class DecoratorMaker { /** * The entry points * * @param args args[0] is the name of the class to decorate */ public static void main(String[] args) throws Exception { createDecoratorFor(args[0]); } /** * Create a decorator for the given class * * @param name The name of the class */ private static void createDecoratorFor(String name) throws Exception { Class parent, returnType, toDecorate; Class[] parameters; int modifiers; Method[] methods; PrintStream out; String decoratorString, nameString, paramString; String returnTypeString, typedParamString; toDecorate = Class.forName(name); // Create an abstract decorator for the parent parent = toDecorate.getSuperclass(); if (parent != null) createDecoratorFor(parent.getCanonicalName()); decoratorString = "Abstract"+toDecorate.getSimpleName()+"Decorator"; out = new PrintStream(new FileOutputStream(decoratorString+".java")); out.print("public abstract class " + decoratorString); if (parent != null) out.print(" extends Abstract"+parent.getSimpleName()+"Decorator"); out.println(); out.println("{"); // Attributes out.println("protected "+toDecorate.getCanonicalName()+ " decorated;"); out.println(); // Constructor out.println("public "+decoratorString+"("+ toDecorate.getCanonicalName()+" decorated)"); out.println("{"); if (parent != null) out.println("\tsuper(decorated);"); out.println("\tthis.decorated = decorated;"); out.println("}"); out.println(); methods = toDecorate.getDeclaredMethods(); for (int i=0; i<methods.length; i++) { modifiers = methods[i].getModifiers(); // Don't include final, native, private, or protected methods if (!Modifier.isFinal(modifiers) && !Modifier.isNative(modifiers) && !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) { // Modifiers out.print(Modifier.toString(modifiers)); // Return type returnType = methods[i].getReturnType(); returnTypeString = returnType.getCanonicalName(); out.print(" " + returnTypeString); // Name nameString = methods[i].getName(); out.print(" " + nameString); // Parameters paramString = "("; typedParamString = "("; parameters = methods[i].getParameterTypes(); if (parameters.length > 0) { paramString += "param0"; typedParamString += parameters[0].getCanonicalName() + " " + "param0"; } for (int p=1; p<parameters.length; p++) { paramString += ", " + "param"+p; typedParamString += ", " + parameters[p].getCanonicalName() +" "+ "param"+p; } paramString += ")"; typedParamString += ")"; out.print(typedParamString); // Body if (Modifier.isAbstract(modifiers)) out.println(";"); else { out.println(); out.println("{"); if (returnTypeString.equals("void")) out.println("\tdecorated."+nameString+paramString+";"); else out.println("\treturn decorated."+nameString+paramString+";"); out.println("}"); } out.println(); } } // End of the class out.println("}"); out.close(); } }