2

I'm doing this a bit backwards because I'm following a specific sequence of project instructions. I have two java classes. One of them simulates the grep function from Linux, and the other simulates the lineCount capability. I have them both implemented, but the NEXT step in the project is to create a superclass using the template method pattern that "will contain all fields and algorithms common to the other two programs".

There is a lot of common functionality between the two, and it is apparent what parts need to be part of the template and which need to be part of the implementations. For example, each of them needs to be able to create File objects based on the path string used to call the method, and search through the File's list method using a regex that is used to call the method. This is common functionality that should definitely be part of the template/abstract class.

It would be nice to be able to declare something like this:

public abstract class RegexCommands{
    protected Variables;
    public Map<things> myMethod(variables){
        //common functionality which includes storing and using the variables
        hookMethod(); //based on what you create in commonFunctionality
        return resultAfterHookMethod;
    }
}

public class Grep extends RegexCommands{
    public hookMethod(){
        class specific things;
    }
}

public class lineCount extends RegexCommands{
    public hookMethod(){
        class specific things;
    }
}

and just call it with

RegexCommands myObject = new Grep();
myObject.myMethod(variables);

and have it return what I'm looking for (grep command for the Grep object, lineCount for the LineCount object). However, the instructions specifically state that it will be called like so:

RegexCommands myObject = new Grep();
myObject.grep(variables);

RegexCommands myObject = new LineCount();
myObject.lineCount(variables);

and also that there are slight differences in the variables used. (lineCount doesn't need a substringSelectionPattern, for example) The way I have it set up now is that the hooked methods call super to their parent, and the template calls myMethod. This is obviously not the way that it is supposed to work. For one thing, it seems like I have had to introduce non-common methods to my template that just call the main template method, which means that one could, theoretically (although I haven't tested it), do something like

RegexCommands myObject = new LineCount();
myObject.grep(variables);

Which is not behavior that I want to allow and seems like it defeats the purpose of using the template. The other problem (that I have actually run into) is that my hookMethods don't seem to have access to the instance variables created in commonFunctionality (ie when I try to access a matcher that was created in commonFunctionality, it returns null even if I declare it as an instance variable instead of a method-level scope, like I would prefer).

So I'm kind of stuck and looking for some help. How do I have these objects use the myMethod pattern in the template without this terrible workaround that destroys the separateness of my objects, and how do I have the non-common methods use ArrayLists and/or Maps from the commonFunctionality without passing EVERYTHING over as parameters (which I have been advised not to do as it ruins the point of using templates)?

Joshua Zollinger
  • 757
  • 1
  • 8
  • 17

2 Answers2

0
RegexCommands myObject = new Grep();
myObject.grep(variables);

RegexCommands myObject = new LineCount();
myObject.lineCount(variables);

This is only possible (in Java) if the interface/abstract class RegexCommands defines both methods. Thus both implementation needs to implement them, too. If you want to stick to that requirement you could do that and let Grep.lineCount() throw some exception.

A workaround could be to make RegexCommands to be a facade that only delegates method calls from RegexCommands.grep() to new Grep().myObject()

However, you should contact the requestor to clarify it.

Andy
  • 1,964
  • 1
  • 15
  • 29
0

For one thing, it seems like I have had to introduce non-common methods to my template that just call the main template method,

Yes you would need to introduce such methods for your given requirement. But as you stated later that this would be incorrect as a LineCount object can call a grep method, this can be avoided by doing a instance of check in the non-common methods you would be writing. Doing the job if it fits the what is expected called or exiting otherwise.

For you original problem that you have run into

my hookMethods don't seem to have access to the instance variables created in commonFunctionality (ie when I try to access a matcher that was created in commonFunctionality, it returns null even if I declare it as an instance variable instead of a method-level scope, like I would prefer).

You can't define a abstract variable in java, the only legal modifier for variable in java are

public, protected, private, static, final, transient, volatile 

you need to have a concrete implementation of commonFunctionality and you can have a getter method for it. You can define a abstract method for this in the abstract class. Refer to the answer of this post for more info Abstract variables in Java?

Community
  • 1
  • 1
mtk
  • 13,221
  • 16
  • 72
  • 112
  • Sorry, that was a typo. It was supposed to be protected variables declared in the abstract class, which seems to be in line with the template pattern method. I've updated the question – Joshua Zollinger Jan 22 '14 at 08:48
  • Also, commonFunctionality wasn't actually supposed to be a class. It was a concrete implementation of the code that contains the functionality common to both classes, equivalent to the "something implementation" shown here: http://www.oodesign.com/template-method-pattern.html the common functionality includes instantiating the variables with ArrayLists from Files based on the Matchers and Patterns used for the regex, but my hook methods don't seem to have access to the variables afterwards. – Joshua Zollinger Jan 22 '14 at 08:54