Alrite, I am gonna jump straight to the code:
public interface Visitor {
public void visitInventory();
public void visitMaxCount();
public void visitCountry();
public void visitSomethingElse();
public void complete();
//the idea of this visitor is that when a validator would visit it, it would validate data
//when a persister visits it, it would persist data, etc, etc.
// not sure if I making sense here...
}
public interface Visitable {
public void accept(Visitor visitor);
}
here is a base implementation:
public class StoreValidator implements Visitor {
private List <ValidationError> storeValidationErrors = new ArrayList<ValidationError>();
public void addError(ValidationError error) {
storeValidationErrors.add(error);
}
public List<ValidationError> getErrors() {
return storeValidationErrors;
}
public void visitInventory() {
// do nothing
}
public void visitMaxCount() {
//do nothing
}
//... etc.. all empty implementations
}
You will see why I did an empty implementation here... I would write a validator now.. which extends StoreValidator
public XYZValidator extends StoreValidator {
#Override
public void visitInventory(Visitable visitable) {
// do something with visitable .. cast it to expected type
// invoke a DAO, obtain results from DB
// if errors found, do addError(new ValidationError()); with msg.
}
#Override
public void visitMaxCount(Visitable visitable) {
//do something with visitable..
}
// I wouldn't implement the rest coz they wouldn't make sense
// in XYZValidator.. so they are defined as empty in StoreValidator.
}
Now here is what a visitable would look like:
public Store implements Visitable {
public void accept(Visitor visitor) {
visitor.visitInventory();
visitor.visitMaxCount();
}
}
I could have code that does something like this on a list of Store objects:
List<Store> stores; //assume this has a list of stores.
StoreValidator validator = new XYZValidator(); //or I would get it from a validatorfactory
for(Store store: stores) {
store.accept(validator); // so even if you send a wrong validator, you are good.
}
Similarly you would have ABCValidator which would provide implementation for other methods (visitCountry / visitSomethinElse) and it would extend from StoreValidator. I would have another type of Object (not Store) defining accept method.
I do see a problem here...
Say, I need a FileValidator which is different from StoreValidator, I would expect it to have none of these business related validations such as visitInventory(), etc. But, by having a single interface Visitor, I would endup declaring all kinds of methods in Visitor interface. Is that correct? Is this how you do it?
I don't know if I got the pattern wrong, or if I am making any sense.
Please share your thoughts.
Some time ago I wrote something similar for my master thesis. This code is slightly
type safe than yours:
interface Visitable<T extends Visitor> {
void acceptVisitor(T visitor);
}
interface Visitor {
/**
* Called before any other visiting method.
*/
void startVisit();
/**
* Called at the end of the visit.
*/
void endVisit();
}
example:
interface ConstantPoolVisitor extends Visitor {
void visitUTF8(int index, String utf8);
void visitClass(int index, int utf8Index);
// ==cut==
}
class ConstantPool implements Visitable<ConstantPoolVisitor> {
#Override
public void acceptVisitor(ConstantPoolVisitor visitor) {
visitor.startVisit();
for (ConstanPoolEntry entry : entries) {
entry.acceptVisitor(visitor);
}
visitor.endVisit();
}
so yes, I think that this definitely a good and flexible design if, and only if, your data changes slower than your behaviour. In my example the data is Java bytecode, that is fixed (defined by the JVM specification). When "behaviour dominates" (I want to dump, compile, transform, refactor, etc my bytecode) the Visitor pattern let you to change/add/remove behaviour without touching your data classes. Just add another implementation of Visitor.
For the sake of simplicity assume that I must add another visit method to my Visitor interface: I would end in breaking all my code.
As alternative I would consider the strategy pattern for this scenario. Strategy + decorator is a good design for validation.
There is a problem with your code as given. The interface you give has methods such as
public void visitInventory();
but you then implement it in XYZValidator as
public void visitInventory(Visitable visitable)
The visitor pattern is a way to implement multiple dispatch in languages that do not do that automatically (such as Java). One of the requirements is that you have a group of related classes (i.e. a set of subclasses with a single super class). You don't have that here, so the visitor pattern is not appropriate. The task you are trying to do, however, is fine, it is just not the Visitor pattern.
In Java, you should think of the Visitor pattern if you have code like
public void count(Item item) {
if (item instanceof SimpleItem) {
// do something
} else if (item instanceof ComplexItem {
// do something else
} else ...
}
particulary if the subclasses of Item are relatively fixed.
I'm using a visitor pattern in a different way.. I have a specific Visitor interface for a type of object and this interface declares only one method - for visiting that object.. like this:
public interface TreeNodeVisitor {
void visit(TreeNode node);
}
the object TreeNode can accept TreeNodeVisitors which means he just calls it's visit method for the node and/or it's children..
The concrete implementation of the visitor implements the visit method and says what the visitor will do.. for example ContryVisitor, InventoryVisitor, etc
This approach should avoid your probleam..
You probably don't want to map a pattern directly to a single interface that everything following that pattern implements. Patterns are NOT Interfaces, they are general plans for implementing a solution.
In your example you would create a StoreVisitor interface and a FileVisitor interface for the different business objects that wish to use the Visitor pattern in the appropriate circumstances.
It might be that different Visitor implementations share common activities - so you could have a superinterface that defines those common functions. You could then code Visitable interfaces to use either the specific Visitable interface or it's superclass as appropriate.
For example, the FileVisitor and SQLTableVisitor interfaces might be a subclass of a DataStoreVisitor interface. Then:
VisitableStore accepts a StoreVisitor,
VisitableFile accepts a Filevisitor, or
VisitableDataStore accepts a DataStoreVistor (which might be an implementation of either FileVisitor or SQLTableVisitor).
forgive the random examples, I hope this makes sense.
Related
We are trying to implement the MVP pattern. Because it requires quite a lot of code just to have a functioning view, we try to use inheritance as much as possible. As I am pretty new to Java, I don't know exactly if I'm doing it right:
So, I started with a very simple Interface which all the views will implement (and the `getName`` method will be used for breadcrumb Feature):
public interface IView {
public String getName();
}
On top of that, I built a BaseView which will be used for most views:
public interface IBaseView extends IView {
public void addListener(IBaseViewListener l);
interface IBaseViewListener {
void viewEntered(Long id);
}
}
And the implementation
public class BaseView extends CustomComponent implements View, IBaseView{
private String name = "";
private List<IBaseViewListener> listeners;
public BaseView(String name) {
this.name = name;
listeners = new ArrayList<IBaseViewListener>();
buildLayout();
}
#Override
public void addListener(IBaseViewListener l) {
listeners.add(l);
}
protected void buildLayout() {
this.setId("base_view");
// initialize layout....
}
#Override
public void enter(ViewChangeEvent event) {
for (IBaseViewListener l : listeners) {
l.viewEntered(id);
}
}
#Override
public String getName() {
return name;
}
}
And last we have a ScaffoldingView which will be used for some views (mainly for mocking):
public interface IScaffoldingView extends IBaseView{
public void showTable(AbstractComponent t);
interface IScaffoldingViewListener extends IBaseViewListener {
void itemSelected(DataBaseObject selectedObject);
}
}
And the implementation:
public class ScaffoldingView extends BaseView implements IScaffoldingView{
private AbstractComponent table = null;
public ScaffoldingView(String name) {
super(name);
}
#Override
protected void buildLayout() {
// here is a lot more code...
}
public void showTable(AbstractComponent t) {
// here is a lot of code...
}
}
First of all:
- Does that approach make any sense? especially the access modifiers. I'm totally weak when it Comes to polymorphism :(
I am very unsure about the handling of the EventListeners. For example: In the constructor of the BaseView, I am implementing the addListener function.
Now, in the ScaffoldingView's, there will be a specialized IScaffoldingViewListener. Will the super class (BaseView) addListener() method be able to handle These IScaffoldingViewListeners?
edit: Sorry, I forgot to mention that View and CustomComponent are some classes of a 3rd Party Framework (Vaadin) which we use and which offer the enter Event in which we call the eventListeners (Presenter).
First, declaring an interface inside another interface is not quite clean, obscures the code quite a bit.
Second, about BaseView which extends CustomComponent, and implements IView and IBaseView, first a small detail, if it implements IBaseView, you do not need to implement IView, as IBaseView already extends IView, but the bigger issue i see is:
If you have a somewhere in some class, a method with an IBaseView as a parameter, but inside that function you expect to be able to use the overrided methods from CustomComponent, you won't be able to, you'll only have the methods declared on IBaseView.
If you wanted to use the CustomComponent methods, you'd had to do a cast inside that method, but that is not clean and a source of bugs, because if in the future, you add more classes that implement IBaseView but do not extend CustomComponent, that function will throw exceptions complaining about casting.
Also, about the ScaffoldingView, if you are going to use it only for mocking purposes in tests and you are extending the IBaseView behaviour, with more methods, if you test a method that has an IBaseView as parameter, you have the same exact situation as before, the method you are testing will not be aware of the IScaffoldingView declared methods, and then it won't use them, and your tests can't be trusted.
P.D.: if you are interested in learning about abstractions and inheritance design, i'd recomend you to check S.O.L.I.D. principles, there's a lot of literature in the web about those.
Edit: Response to your comment
First you need to ask yourself without thinking about internal details or implementations or testing or anything else, what are the behaviour my Views have? are they all behaving the same way? do i have different types of views or not really? Once you answer these questions and got an idea of what is going on, you'll have what it will need to design the interface hierarchy, and thats what is going to be exposed to the rest of the system.
You can (optionally) have abstract classes that derive from those interfaces, where you can provide some initialization, defaults, but, do not go further in offering more functionality than the interface offers, you can have some extra methods, but only for internal use.
And then you can derive the actual implementation of the views from the interface or the intermediate abstract classes if you have defined any.
Just think of this as a black box, in which the only thing you can see are the input and output interfaces, everything else that is going inside that box, the rest of the system doesn't and shouldn't need to know about.
Can't really give you specific solution because i'm not aware of the needs of your application.
I'm implementing a service class having a method like this:
public void makeSomething() {
// some logic...
// [optional logic]
// some other logic...
}
This is a concrete class and it can be instantiated and used "as is", but I somethimes need to extend it and override the makeSomething() method adding some additional logic (in the middle). I mean: I need to use the same logic in parent method, but i need to extend logic before return.
My first idea was to add an "optional" method in the middle of the original method:
public void makeSomething() {
// some logic...
optionalOperation();
// some other logic...
}
and eventually override the optionalOperation() method in extending classes. But I don't like this: I will have an empty method doing nothing in my original class...
So, is there a better way to design my method? Is there some design pattern addressing my issue?
The design pattern is called Template method and it works exactly the way you don't like, I'm afraid.
For example, Spring's code is full of such empty protected methods waiting for you to add something custom into them.
i can think of 2 ways:
inheritance and common 'lifecycle' aka Template Method. it's very problematic to maintain when it's in the middle of your business logic
strategy pattern. try to refactor and pass strategy to the method or object owning this method. if you can use any functional language you can take it to the extreme and instead of passing strategy use a function composition: define 'makeSomething' as a function of other functions. and one of 'makeSomething' will contain also 'optionalOperation' in it's definition. but it may require really heavy refactoring
A simple solution would be this:
public class AClass {
public void makeSomething() {
someLogic();
someOtherLogic();
}
protected void someLogic() {
System.out.println("some logic");
}
protected void someOtherLogic() {
System.out.println("some other logic");
}
}
public class AnEnhancedClass extends AClass {
#Override
public void makeSomething() {
someLogic();
System.out.println("optional operation");
someOtherLogic();
}
}
I've read about abstract factory patter on wiki. But I don't understand really profit by using this pattern. Can you get an example in which is hard to avoid abstract factory pattern. Consider the following Java code:
public abstract class FinancialToolsFactory {
public abstract TaxProcessor createTaxProcessor();
public abstract ShipFeeProcessor createShipFeeProcessor();
}
public abstract class ShipFeeProcessor {
abstract void calculateShipFee(Order order);
}
public abstract class TaxProcessor {
abstract void calculateTaxes(Order order);
}
// Factories
public class CanadaFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new CanadaTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new CanadaShipFeeProcessor();
}
}
public class EuropeFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new EuropeTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new EuropeShipFeeProcessor();
}
}
// Products
public class EuropeShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Europe specific ship fee calculation
}
}
public class CanadaShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Canada specific ship fee calculation
}
}
public class EuropeTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Europe specific tax calculation
}
}
public class CanadaTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Canada specific tax calculation
}
}
If we need to just create objects in a code below 1-2 times in a code then we can use just new operator. And why we need in abstract factory?
You are missing half of the work :)
void processOrder(FinancialToolsFactory ftf,Order o) {
tft.createTaxProcessor().calculateTaxes(o);
tft.createShipFeeProcessor().calculateShipFee(o);
}
this code works as well as you pass a canadian or european implementation of FinancialToolsFactory (you can externalize the implementor class to external resource and instantiate with a Class.newInstance(), for example).
In this case one of the real benefits of pattern usage is not writing the code that implements the pattern, but who use that code!
PS: My answer is intentionally incomplete and try to answer just this specific question; a discussion about pattern and their benefits is too big!
You'd take advantage of this pattern if you were to support different implementations transparently. By delegating the decision of which implementation to use to the factory, you have a single point in your code where that decision is made (a.k.a. single responsibility).
The abstract factory pattern takes this concept beyond by aggregating related factories, such as different financial tools factories in your sample.
Now, if you only instantiate your financial tools once or twice in your code, using factories is over-engineering. The gain comes when you need to instantiate different implementations of the same interfaces in different places many times and you want to be able to work without worrying about which implementation you are using or how that decision is made.
There are quite some resources about this pattern on the web, and it's hard to guess what might be the best way of explaining its purpose in a way that sounds "plausible" for you.
But I think that the key point is:
With this pattern, someone who wants to create an instance of a particular implementation of an interface does not need to know what this particular implementation is. The call to the new operator is hidden inside the factory, and the user of the factory does not need to know the concrete class.
This makes it easier to switch the implementation later: You don't have to find and adjust all places where new ConcreteClass() was called and change it to new OtherConcreteClass() in order to use a different implementation. You just pass a different factory around, and everybody who uses this factory automatically creates instances of OtherConcreteClass (without even knowing that he does so...)
Code 1:
public class User1 implements MyInterface
{
#Override
public void doCalculation() { }
}
public class User2 implements MyInterface
{
#Override
public void doCalculation() { }
}
interface MyInterface
{
public void doCalculation();
}
Code 2:
public class User1
{
public void doCalculation() { }
}
public class User2
{
public void doCalculation() { }
}
Here in my Code 1 I have MyInterface which has an empty method doCalculation().
That doCalculation() is used by user1 and user2 by implementing MyInterface.
Where as in my Code 2 I have two different classes with defined doCalculation() method.
In both the cases code1 and code2 I myself have to write the implementation. My method doCalculation() is just an empty method.
So what is the use of MyInterface here?
It only provides me the method name or skeleton (is that the only advantage of interface)?
Or else would I save any memory while using MyInterface?
Is that, it only provides the empty method for an class which implements it, then why not I define it by myself as I have done in my code2.
More than that is there any more advantage on using an interface.
Interfaces are used a lot because they are basically a blueprint of what your class should be able to do.
For example, if you are writing a video game with characters, you can have an interface that holds all the methods that a character should have.
For example
public interface Character {
public void doAction();
}
And you have 2 characters, for example an ally and an enemy.
public class Ally implements Character {
public void doAction() {
System.out.println("Defend");
}
}
public class Enemy implements Character {
public void doAction() {
System.out.println("Attack");
}
}
As you can see, both classes implement the interface, but they have different actions.
Now you can create a character which implements your interface and have it perform its action. Depending on if it's an enemy or an ally, it'll perform a different action.
public Character ally = new Ally();
public Character enemy = new Enemy();
And in your main program, you can create a method that accepts any object that implements your interface and have it perform it's action without knowing what kind of character it is.
void characterDoAction(Character char) {
char.doAction();
}
If you would give ally to this method, the output would be:
Defend
If you would give enemy to this method, the output would be:
Attack
I hope this was a good enough example to help you understand the benefits of using interfaces.
There are a lot of advantages of interface driven programming.
What does "program to interfaces, not implementations" mean?
Basically you are defining a contract in an interface and all the classes which implement the interface have to abide by the contract.
Answers to your queries:
1.It only provides me the method name or skeleton (is that the only advantage of interface)?
--> Its not just about providing the method name but also defining what the class implementing the interface can do.
2.Or else would I save any memory while using MyInterface?
--> Nothing to do with the memory
Is that, it only provides the empty method for an class which implements it, then why not I define it by myself as I have done in my code2.
--> see the advantages of interface driven programming.
4.More than that is there any more advantage on using an interface.
--> Plenty,specially dependency injection , mocking , unit testing etc.
A very good explanation can be found here when-best-to-use-an-interface-in-java. It really depends on what you're building and how much scalability, code duplications, etc you want/don't want to have.
Many classes use interfaces to perform some function, relying on other programmers to implement that interface respecting the contract that an interface govern. Such classes are, for example, KeyListeners, MouseListeners, Runnable, etc.
For example: JVM knows what to do with a Thread, how to start it, stop it, manipulate it, but it does not know what your Thread should do, so you have to implement the Runnable interface.
Interfaces offer you a level of abstraction which can be leveraged in other classes. For example, if you have an interface called GemetricFigure, in a class that prints girth of a GeometricFigure you could iterate over a list of all GeometricFigures like:
public class Canvas {
private List<GeometricFigure> figures;
public void print() {
for (GeometricFigure figure : figure) {
System.out.println(figure.getGirth());
}
}
}
And if the GeometricFigure has only that method:
public interface GeometricFigure {
public Double getGirth();
}
You wouldn't care how Square or Circle implement that interface. Otherwise, if there were no interface, you could not have a list of GeometricFigures in Canvas, but a list for every figure type.
With the interface approach you can do the following:
List<MyInterface> list = new ArrayList<MyInterface();
list.add(new User1());
list.add(new User2());
for(MyInterface myInterface : list) {
myInterface.doClaculation()
}
This does not work with the second approach. Interfaces are for the code that use your classes - not for your classes themselves.
You can use interfaces in many cases. Also the situation you describes: You needn't to know, which implementation you have.
For example you have anywhere in your code a method, that returns the current singed in user even you don't know if it is User1 or User2 implementation, however that both of them can calculate something by method doCalculation. I add a really dummy example of that situation:
public void dummyExampleCalculation() {
getCurrentUser().doCalculation();
}
public MyInterface getCurrentUser() {
if(...) {
return new User1();
} else {
return new User2();
}
}
That is what Object Oriented Programming is all about.Interfaces are used to perform polymorphism. You said, you can implementations in code2 for both the classes, what if in future there is user3 who needs to doCalculation. You can just implement that interface and write your calculation in your own form.
When you want to provide a basic functionality to all your users abstract classes comes into picture where in you can declare an abstract method do calculation and provide implementation of that basic functionalities which then each user will extend and can doCalculation in their own way.
Interface is like a contract that your implementing class should satisfy. Usually, you will write an interface and make all your other class's implement it with their own implementation.
Example:
interface IExporter {
public void export();
}
public class PDFExport implements IExporter {
public void export(){
//code for PDF Exporting
}
}
public class XLSExport implements IExporter {
public void export(){
//code for XLS Exporting
}
}
public class DOCExport implements IExporter {
public void export(){
//code for DOC Exporting
}
}
Interface in Java is used to impose an implementation rule on classes. That means you can declare the signature of functions in interfaces and then implement these function in various classes by exactly following the function signature.
You can see a clear and realistic example on the following webpage
http://www.csnotes32.com/2014/10/interface-in-java.html
I've run into a situation in which I was to extend the functionality of a given class, but I'm not sure of the best way to go about this. I started by invoking functionality "upwards" and have now switched to "downwards", but I see issues with both. Let me explain what I mean. First, the "upwards" approach:
public class ParentValidator
{
public void validate() {
// Some code
}
}
public class ChildValidator extends ParentValidator
{
#Override
public void validate() {
super.validate();
// Some code
}
}
public class GrandchildValidator extends ChildValidator
{
#Override
public void validate() {
super.validate();
// Some code
}
}
This functions perfectly well, but it requires that I always remember to place super.validate() in my method body or the logic in the parent class(es) won't be executed. In addition, extension in this manner can be considered "unsafe" due to the fact that a child class could actually replace/modify the code defined in the parent class. This is what I call invoking methods "upwards" because I'm invoking methods from higher level classes as I go.
To counter these shortfalls, I decided to make ParentValidator.validate() final and have it invoke a different method. Here's what my code was modified to:
public class ParentValidator
{
public final void validate() {
// Some code
subValidate();
}
protected void subValidate() {}
}
public class ChildValidator extends ParentValidator
{
#Override
public final void subValidate() {
// Some code
subSubValidate();
}
protected void subSubValidate() {}
}
public class GrandchildValidator extends ChildValidator
{
#Override
public void subSubBalidate() {
// Some code
subSubSubValidate();
}
protected void subSubSubValidate();
}
This is what I was referring to when I say that I'm calling downwards as each class invokes methods on classes "down" the inheritance chain.
Using this approach, I can be guaranteed that the logic in the parent class(es) will be executed, which I like. However, it doesn't scale well. The more layers of inheritance I have, the uglier it gets. At one level, I think this is very elegant. At two levels, it starts to look shoddy. At three or more, it's hideous.
In addition, just as I had to remember to invoke super.validate() as the first line of any of my children's validate methods, I now have to remember to invoke some "subValidate" method at the end of any of my parent's validate methods, so that didn't seem to get any better.
Is there a better way to do this type of extension that I haven't even touched on. Either of these approaches have some serious flaws and I'm wondering if there's a better design pattern I could be using.
In what you describe as your first approach you are using simple inheritance, your second approach is closer to what the Gang of Four [GoF] called a Template Method Pattern because your parent class is using the so-called Hollywood Principle: "don't call us, we'll call you".
However, you could benefit from declaring the subvalidate() method as abstract in the parent class, and by this, make sure all subclasses are forced to implement it. Then it would be a true template method.
public abstract class ParentValidator
{
public final void validate() {
//some code
subValidate();
}
protected abstract void subValidate() {}
}
Depending on what you are doing there are other patterns that could help you do this in a different manner. For instance, you could use a Strategy Pattern to peform the validations, and by this favoring composition over inheritance, as suggested before, but a consequence is that you will need more validation classes.
public abstract class ParentValidator
{
private final ValidatorStrategy validator;
protected ParentValidator(ValidatorStrategy validator){
this.validator = validator;
}
public final void validate() {
//some code
this.validator.validate();
}
}
Then you can provide specific validation strategies for every type of Validator that you have.
If you want to get the best of both worlds you might considering implementing the solution as a Decorator Pattern where subclasses can extend the functionality of a parent class and still stick to a common interface.
public abstract class ValidatorDecorator implements Validator
{
private final Validator validator;
protected ParentValidator(Validator validator){
this.validator = validator;
}
public final void validate() {
//some code
super.validate(); //still forced to invoke super
this.validator.validate();
}
}
All patterns have consequences and advantages and disadvantages that you must consider carefully.
I'd prefer to 1) program against interfaces, and 2) opt for composition over inheritance. This is how I have done. Some people like it, some do not. It works.
// java pseudocode below, you'll need to work the wrinkles out
/**
* Defines a rule or set of rules under which a instance of T
* is deemed valid or invalid
**/
public interface ValidationRule<T>
{
/**
* #return String describing invalidation condition, or null
* (indicating then that parameter t is valid */
**/
String apply(final T t);
}
/**
* Utility class for enforcing a logical conjunction
* of zero or more validatoin rules on an object.
**/
public final class ValidatorEvaluator
{
/**
* evaluates zero or more validation rules (as a logical
* 'AND') on an instance of type T.
**/
static <T> String apply(final T t, ValidationRule<T> ... rules)
{
for(final ValidationRules<T> v : rules)
{
String msg = v.apply(t);
if( msg != null )
{
return msg; // t is not valid
}
}
return null;
}
}
// arbitrary dummy class that we will test for
// i being a positive number greater than zero
public class MyFoo
{
int i;
public MyFoo(int n){ i = n; }
///
}
public class NonZeroValidatorRule implements ValidatorRule<MyFoo>
{
public String apply(final MyFoo foo)
{
return foo.i == 0 ? "foo.i is zero!" : null;
}
}
// test for being positive using NonZeroValidatorRule and an anonymous
// validator that tests for negatives
String msg = ValidatorEvaluator.apply( new MyFoo(1),
new NonZeroValidatorRule(),
new ValidatorRule<MyFoo>()
{
public String apply(final MyFoo foo)
{
return foo.i < 0 ? "foo.i is negative!" : null;
}
}
);
if( msg == null )
{
\\ yay!
...
}
else
{
\\ nay...
someLogThingie.log("error: myFoo now workie. reason=" + msg );
}
More complex, non-trivial evaluation rules can be implemented this way.
The key here is that you should not use inheritance unless there exists a is-a relationship. Do not use it just to recycle or encapsulate logic. If you still feel you need to use inheritance, then don't go overkill trying to make sure that every subclass executes the validation logic inherited from the superclass. Have implementations of each subclass do an explicit execution on super:
public class ParentValidator
{
public void validate() { // notice that I removed the final you originally had
// Some code
}
}
pubic class ChildValidator extends ParentValidator
{
#Override
public void validate() {
// Some code
super.validate(); // explicit call to inherited validate
// more validation code
}
}
Keep things simple, and don't try to make it impossible or fool-proof. There is a difference between coding defensively (a good practice) and coding against stupid (a futile effort.) Simply lay out coding rules on how to subclass your validators. That is, put the onus on the implementors. If they cannot follow the guidelines, no amount of defensive coding will protect your system against their stupidity. Ergo, keep things clear and simple.
I prefer to using composition over inheritance if your subSubSubValidate is related general functionality. You can extract new class and move it there than you can use it without inheritance in the other classes.
There is also
"Favor 'object composition' over
'class inheritance'." (Gang of Four
1995:20)
maybe a look at the visitor pattern may help you to develop your pattern.
Here are some information on it : http://en.wikipedia.org/wiki/Visitor_pattern