I am designing a java system where users can define some rules in a fluent style.
Rules have many properties, which are partly mutually exclusive.
We use a builder pattern with validation for this.
To make the system easier to use, we want to introduce a StepBuilder, to guide the user to all necessary steps.
There are different types of rules, but all share some common properties.
Current System:
abstract BaseBuilder<T extends BaseBuilder<T>> {
protected String property1;
protected String property2;
protected String property3;
abstract Rule build();
public T withProperty1(String data) {
this.property1 = data;
return this;
}
public T withProperty2(String data) {
this.property2 = data;
return this;
}
public T withProperty3(String data) {
//this should only be possible if property2 is not set or similar logic
this.property3 = data;
return this;
}
}
//there are a few others like this e.g. SpecialBuilder1-10
class SpecialRuleBuilder extends BaseBuilder<SpecialBuilder> {
protected String special1;
protected String special2;
public T withSpecial1(String data) {
this.special1 = data;
return this;
}
public T withSpecial2(String data) {
this.special2 = data;
return this;
}
#Override
Rule builder() {
return new SpecialRule(property1, property3, special1, special2, ....);
}
static SpecialRuleBuilder builder() {
return new SpecialRuleBuilder();
}
}
class BuilderTest() {
//User can set anything, no steps are enforced at compile time
Result result = SpecialBuilder.builder()
.property1("some")
.special2("thing")
.build();
}
How can we use a StepBuilder including a hierarchy (parent class), so the user cannot get to the same step twice cannot accidentally go back to a previous base step and set some mutually exclusive properties again.
Ideally the user should not be aware of all the special builders and have the same entry point and guided steps. For example:
Result result = GeneralBuilder.builder()
.withBaseProperty1("asdas") <-- Step 1
.withBaseProperty2("asd") <-- Step 2, Step 3 is now not visible, continue with all possible special options
.withSpecial1("asd") <-- no we are in the step of one concrete builder, and should not get "out" again, not even to the base methods
I know how to define the interface steps, I just dont know how to include all possible starting steps of the special builders at the end of the base steps, since the higher interface/class should probably not rely on the lower parts of the hierarchy.
Is this somehow possible?
This is a bad idea; the sheer amount of code you need to write is staggering. Also, whilst the appeal of a guided 'auto-complete' experience in an IDE is obvious, realize that sometimes builders are used in a more fluent (heh) fashion: Some code makes a builder, sets half the stuff, and then returns the builder so that other code can pick up where it left off. Or, a utility method that takes a builder as param, and sets a few things on it. These use cases become awkward to impossible when you go down this path. So, you spend a ton of time writing this code and it's not even a clean win, API-wise!
If you want to ignore my advice and do it anyway, well, okay. Your funeral. A warned person counts for two, and all that. It looks like this:
public interface BridgeBuilder1 {
public BridgeBuilder2 name(String name); // mandatory
}
public interface BridgeBuilder2 {
public BridgeBuilder3 buildYear(int year); // mandatory
}
public interface BridgeBuilder3 {
// one of these two is mandatory, and they are mutually exclusive.
public BridgeBuilder4 lanes(int lanes);
public BridgeBuilder4 width(int widthInM);
}
public interface BridgeBuilder4 {
// optional stuff, and the build itself.
public BridgeBuilder4 color(Color c);
public BridgeBuilder4 country(String name);
public Bridge build();
}
// intentionally private class! Should be an inner class
// of your public Bridge class.
private static class BridgeBuilder implements BridgeBuilder1, BridgeBuilder2, BridgeBuilder3, BridgeBuilder4 {
private String name;
public BridgeBuilder2 name(String name) {
this.name = name;
return this;
}
// the fluent, chaining 'setters' for _ALL_ properties here.
// Match the return types exactly to how they
// are defined in the interfaces.
public Bridge build() {
return new Bridge(name, year, ....);
}
}
...
public class Bridge {
Bridge(String name, ...) {
// a package private constructor.
}
public static BridgeBuilder1 builder() {
return new BridgeBuilder();
}
}
That should be sufficient to highlight how this works.
But don't.
NB: The actually good solution is to enshrine the notion of a builder into the editor/lang tooling itself. An eclipse or intellij plugin, in other words. Annotations can be used to identify everything (annotate a builder() method to indicate it makes a builder, annotate a class that it is a builder class, etc), then annotate each method in a builder as being optional or not, and as being multiple or not (imagine a builder method that is intended to be invoked multiple times to e.g. fill a list). Armed with that info a plugin can 'fix' the auto-complete dialog to skip all the crap from j.l.Object, and to show all mandatory fields in bold, all already-set stuff greyed out, all optionals in normal colour, and the build method greyed out until all mandatories are set, and bold once they are. That's the real solution. I invite anybody to write these plugins instead of wasting time maintaining this ridiculous-length API extravaganza to create a hampered take on the idea.
Related
I have a lot of classes implementing a "common" interface called Setter.
public interface Setter {
Result set(Config config, int entityId);
enum Result {
HANDLED, HANDLING_ERROR, REJECTED
}
}
An example of an implementation looks like this, it sets in the world a 'number' value for a given 'entity' distinguished by its entityId:
public class NumberSetter implements Setter {
private World world;
private Assets assets;
public NumberSetter(World world, Assets assets) {
this.world = world.
this.assets = assets;
}
#Override
public Result set(Config config, int entityId) {
if (config instanceof NumberConfig numberConfig) {
world.passNumber(entityId, numberConfig.number);
return Result.HANDLED;
} else {
return Result.REJECTED;
}
}
}
Please do notice, that the Config object is cast to a specific NumberConfig, otherwise the Setter implementation signals it didn't handle the argument.
I am using a Set of these Setters in a network-enabled class, where it tries to match a super-type Config object against one of these Setters from the Set. (The naming might be subject to change lmao.) The code below handles a network package by passing it to all of the Setters in the Set and checks if there were any errors or if no Setter handled the package. If the check passes then the package wasn't handled properly and the Handler returns a NOT_HANDLED which later crashes the program because I'm still at the development stage.
public class ConfigNetworkHandler implements NetworkHandler {
private final Assets assets;
private final Set<Setter> setterSet;
public ConfigNetworkHandler(
Assets assets,
Set<Setter> setterSet
) {
this.assets = assets;
this.setterSet = setterSet;
}
#Override
public boolean handle(WebSocket webSocket, int worldEntity, Component component) {
var configId = ((ConfigId) component).getId();
var config = assets.getConfigs().get(configId);
var setterResults = setterSet.stream()
.map(setter -> setter.set(config, worldEntity))
.toList();
var anyErrors = setterResults.stream().anyMatch(HANDLING_ERROR::equals);
var wasHandled = setterResults.stream().anyMatch(HANDLED::equals);
if (anyErrors || !wasHandled) {
return NOT_HANDLED;
}
return FULLY_HANDLED;
}
}
I don't like it how I am not using Java's type system properly. I don't know how to do it otherwise, without manually providing a Map between ConfigId's and the Setters, which I would rather not do, because the ConfigIds aren't known at compile-time. The NetworkHandler-type-stuff is kind of similar but there are a lot less of them and they will probably be refactored in a similar way (there is also a lot fewer of them, so it's not a practical issue).
I like the current solution because it allows me to add and remove Setters without worrying about the other ones and also I don't need to change the implementation of ConfigNetworkHandler, because it's provided a Set. I don't like it, because it requires list traversing, doesn't seem "idiomatic" for Java, returns weird Results instead of just not being called because it doesn't accept the type, and FEELS like there should be something else.
Do you have an idea how to approach this differently?
I am constructing a car class that has an engine, gearbox, clutch etc.
I don't want a bloated constructor that takes 7 parameters, so I decided to use the builder pattern.
All the parts are required.
However, how do I make the user of the Car class use all the parts' setters, as they are all mandatory?
Throw exceptions?
public class Car {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
public Car(Builder builder) {
engine = builder.engine;
chassis = builder.chassis;
gearBox = builder.gearBox;
coupe = builder.coupe;
exterior = builder.exterior;
interior = builder.interior;
clutch = builder.clutch;
}
public static class Builder {
private Engine engine;
private Chassis chassis;
private GearBox gearBox;
private Coupe coupe;
private Exterior exterior;
private Interior interior;
private Clutch clutch;
private Car build() {
return new Car(this);
}
public Builder setEngine(#NonNull Engine engine) {
this.engine = engine;
return this;
}
public Builder setChassis(#NonNull Chassis chassis) {
this.chassis = chassis;
return this;
}
public Builder setGearBox(#NonNull GearBox gearBox) {
this.gearBox = gearBox;
return this;
}
public Builder setCoupe(#NonNull Coupe coupe) {
this.coupe = coupe;
return this;
}
public Builder setExterior(#NonNull Exterior exterior) {
this.exterior = exterior;
return this;
}
public Builder setInterior(#NonNull Interior interior) {
this.interior = interior;
return this;
}
public Builder setClutch(#NonNull Clutch clutchs) {
this.clutch = clutchs;
return this;
}
}
}
I want the user so call ALL of the builder setters, not an optional subset of them. How do I do that?
Is there another way to construct a car without having a huge constructor that takes so many parameters?
EDIT: I looked at The builder pattern and a large number of mandatory parameters but there is no solution there that prevents huge constructors.
Builders are for things where lots of parts are optional or you have many different configurations. The build() method then makes sure that the specific configuration works. A HTML builder makes sense, a string builder not so much.
If there are no optional parts, you have these options:
Get rid of the builder and use a constructor that requires all parts. Classic solution, least readable and hard to extend.
You can throw an exception in the build() method for each missing part. That's a lot of code to write and kind of goes against the pattern.
You can add methods with more than a single argument to the builder. That's a mix of the two above. You're still using the builder pattern (so you can easily add more configurations later) but your API also communicates more clearly which parts are mandatory.
As an example, you might get an engine in the future which already contains the gearbox or which requires a specific gearbox (i.e. when you use this engine, you also select the gearbox). To implement this, you'd create a second builder method which just asks for the engine and determines the gearbox automatically.
Use a factory with protected methods which build the parts. The factory will make sure all parts are supplied to the car. If you want to replace a part, you can override the protected method. This works well if you have lot of defaults and only 2-3 useful configurations.
Use several builders. Instead of build everything from individual screws, create your car from larger building blocks: propulsion, interior, body. Create your car from those three with a constructor (three parameters is good). Now you can use three builders to create those three. Try to find a balance between required and optional elements.
Chain builders as explained by mlk below. This forces the user to fill in all parts (since you can only call the build() at the end of the chain). Main drawbacks here are: A lot of code to write and hard to follow from the user perspective since the code is spread over many classes. jOOQ is an example here; the project implements the SQL syntax as a chain of builders.
Remember what the builder pattern tries to solve: They make it easy to add more parts since all existing code doesn't need to change if the new part is optional. If the new part is mandatory, the builder pattern becomes a liability: With a huge (unreadable) constructor, you get compile errors in all places that needs fixing. The builder will fail at runtime in this case; you need an IDE to find all the places which need fixing.
If the primary reason for this is to have a fluent API rather than removing a bloated constructor then you could chain builders together:
class Engine {}
class Door {}
class Car {
Car(Engine engine, Door door) {
}
}
class CarBuilder {
private Engine engine;
public CarWithEngineBuilder withEngine(Engine engine) {
this.engine = engine;
return new CarWithEngineBuilder();
}
class CarWithEngineBuilder {
private Door door;
public CarWithEngineAndDoor withDoor(Door door) {
this.door = door;
return new CarWithEngineAndDoor();
}
class CarWithEngineAndDoor {
public Car build() {
return new Car(engine, door);
}
}
}
}
class TestStuff {
{
Car c = new CarBuilder().withEngine(new Engine()).withDoor(new Door()).build();
}
}
Or if your main concern is the size of the constructor, maybe the constructor is telling you something, and you could look at the class and see is some parts are logically "together". I.e. are Engine, Gears & Brake are one part of larger component? Should the car be DriveSystem and Chassis (which includes an Exteriorand Interior). Then constructor for Car has a manageable number of parameters, as does DriveSystem and Chassis?
If you look to the builder pattern, you can find out, that there is important thing, which you do not have, and it is Director. And also Builder interface, that defines all the required methods.
Director should call all methods required on interface builder (in your case "build engine, build coupe etc."). The class implementing the Builder interface must override all methods or the code does not even compile.
I am working on a component which is supposed to:
receive data (collection of items) from some external calculation component. I expect about 100-1K of items on input on each request.
validate data, calculate some attributes if missing
persist data
There are about ten types of items. I use inheritance to model items. I have a base item class with common attributes and calculations and subclasses implementing type specific problems. Similar to following example:
public abstract class BaseItem {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
}
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
public class ItemA1 extends ItemA {
BigDecimal extraValue;
#Override
public void postCalucate() {
//some A1 subtype specific calculations
valid = isA1ItemValid();
super.postCalucate();
}
}
public class ItemB extends BaseItem {
Integer size;
#Override
public void postCalucate() {
//some B specific calculations
super.postCalucate();
}
}
Is there any better way/pattern to do my task? Any advices?
The pattern you are trying to use is fairly sound. In general, I would probably suggest the use of an interface instead of a BaseItem class, since it might not contain that much common functionality.
In general, most people seem to recommend defining interfaces for your classes to implement. If absolutely you want to share common code in an AbstractClass, I would recommend that class implementing the interface, since this pattern would lend itself to greater extensibility and flexibility in the future.
As such, you would first begin by defining what an Item is for you. For me, it seems that an Item is three things in your use case: one, it must define the postCalculate() method that will be called on all Items. Second, it must provide an isValid() method. And third, it should also provide a getName() method.
public interface Item {
void postCalucate();
boolean isValid();
String getName();
}
Then you would begin implementing your Abstract class. Do this only if it really is necessary to share a codebase between all your items.
public abstract class BaseItem implements Item {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
public boolean isValid() {
return valid;
}
public String getName() {
return name;
}
}
If BaseItem.postCalculate() is something that will need to be done for all items, this is a good way to do it. If you're not entirely sure, it might be a good idea instead to define a method somewhere in a Helper or Tool class that performs this common calculation for items, and is called by the postCalculate() methods:
public class ItemTools {
public static boolean meetsRequirements(Item item) {
return item.isValid && item.getName() != null;
}
}
This, many would argue, gives you an easier time as your requirements on BaseItem may change over time.
Regardless of which route you go there, now you'll just have to define your actual items:
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
While the general advice is to avoid over-usage of inheritance, this is no case of over-usage. So, go ahead with this approach.
Apart from that: Your code shows problems with encapsulation. You shouldn’t have all these non-private field. As a reminder: no visibility at all is package-visibility (visible in the whole package and to all sub-classes). Make your fields private.
A priori, your proposal seems reasonable.
But to be sure, you have to look at all the events of the life cycle of your objects:
instantiation
use, read
collaboration
persistence
...
Let's say I have an abstract class (BaseThing). It has one required parameter ("base required") and one optional parameter ("base optional"). I have a concrete class that extends it (Thing). It also has one required parameter ("required") and one optional parameter ("optional"). So something like:
public abstract class BaseThing {
public static final String DEFAULT_BASE_OPTIONAL = "Default Base Optional";
private final String baseRequired;
private String baseOptional = DEFAULT_BASE_OPTIONAL;
protected BaseThing(final String theBaseRequired) {
this.baseRequired = theBaseRequired;
}
final void setBaseOptional(final String newVal) {
this.baseOptional = newVal;
}
public final void selfDescribe() {
System.out.println("Base Required: " + baseRequired);
System.out.println("Base Optional: " + baseOptional);
selfDescribeHook();
}
protected abstract void selfDescribeHook();
}
and:
public final class Thing extends BaseThing {
public static final String DEFAULT_OPTIONAL = "Default Optional";
private final String required;
private String optional = DEFAULT_OPTIONAL;
Thing(final String theRequired, final String theBaseRequired) {
super(theBaseRequired);
required = theRequired;
}
#Override
protected void selfDescribeHook() {
System.out.println("Required: " + required);
System.out.println("Optional: " + optional);
}
void setOptional(final String newVal) {
optional = newVal;
}
}
I want to have a Joshua Bloch-style builder for Thing objects. More generally, though, I want to make it easy for concrete implementations of BaseThing to have builders, so what I really want (I think) is a BaseThing builder that can easily be used to make a ThingBuilder, or an OtherThingBuilder, or a SuperThingBuilder.
Is there a better way than the following that I've come up with (or are there problems with what I've come up with)?
public abstract class BaseThingBuilder<T extends BaseThing> {
private String baseOptional = BaseThing.DEFAULT_BASE_OPTIONAL;
public BaseThingBuilder<T> setBaseOptional(final String value) {
baseOptional = value;
return this;
}
public T build() {
T t = buildHook();
t.setBaseOptional(baseOptional);
return t;
}
protected abstract T buildHook();
}
and:
public final class ThingBuilder extends BaseThingBuilder<Thing> {
private final String baseRequired;
private final String required;
private String optional = Thing.DEFAULT_OPTIONAL;
public ThingBuilder(final String theRequired,
final String theBaseRequired) {
required = theRequired;
baseRequired = theBaseRequired;
}
public ThingBuilder setOptional(final String value) {
optional = value;
return this;
}
protected Thing buildHook() {
Thing thing = new Thing(required, baseRequired);
thing.setOptional(optional);
return thing;
}
}
Which can be used to build Thing objects in a manner similarly to the following:
BaseThingBuilder<Thing> builder =
new ThingBuilder("Required!", "Base Required!")
.setOptional("Optional!")
.setBaseOptional("Base Optional!");
Thing thing = builder.build();
thing.selfDescribe();
Which outputs:
Base Required: Base Required!
Base Optional: Base Optional!
Required: Required!
Optional: Optional!
One issue that I know about, but that I don't consider particularly important (though if it can be improved it would be nice to do so) is that you have to set all non-base options before you set any base option: Doing otherwise would result in a syntax error, as setBaseOptional() returns a BaseThingBuilder rather than a ThingBuilder.
Thanks in advance.
I don't think it's a good idea to think of builders that way. A hierarchy of builders usually leads to headaches and fragile code.
Cutting down the amount of code that needs to be written in the concrete builders and reusing logic from the base builder is closely tied to the domain. It's not easy to develop a general solution. But, let's try to go through an example anyway:
public interface Builder<T> {
T build();
}
public class Person {
private final String name;
//the proper way to use a builder is to pass an instance of one to
//the class that is created using it...
Person(PersonBuilder builder) {
this.name = builder.name;
}
public String getName(){ return name; }
public static class PersonBuilder implements Builder<Person> {
private String name;
public PersonBuilder name(String name){ this.name = name; return this; }
public Person build() {
if(name == null) {
throw new IllegalArgumentException("Name must be specified");
}
return new Person(this);
}
}
}
Groovy, baby! Now what? Maybe you want to add a class to represent a student. What do you do? Do you extend Person? Sure, that's valid. How about taking a more "strange" route and attempting aggregation? Yep, you can do that too... Your choice would have an affect on how you will end up implementing builders. Let's say you stick to the traditional path and extend Person (you should already starting asking yourself, does it make sense for Person to be a concrete class? If I make it abstract, do I really need a builder? If the class is abstract should the builder be abstract?):
public class Student extends Person {
private final long id;
Student(StudentBulder builder) {
super(builder);
this.id = builder.id;
}
public long getId(){ return id; }
//no need for generics, this will work:
public static class StudentBuilder extends PersonBuilder {
private long id;
public StudentBuilder id(long id){ this.id = id; return this; }
public Student build() {
if(id <= 0) {
throw new IllegalArgumentException("ID must be specified");
}
return new Student(this);
}
}
}
Ok, this looks exactly like what you wanted! So, you try it:
Person p = new PersonBuilder().name("John Doe").build();
Student s = new StudentBuilder().name("Jane Doe").id(165).build();
Looks great! Except, it doesn't compile... There's an error at line 2 and it states The method id(int) is undefined for the type Person.PersonBuilder. The problem is that PersonBuilder#name returns a builder of type PersonBuilder, which isn't what you want. In StudentBuilder you actually want the return type of name to be StudentBuilder. Now, you think ahead and realize that if anything extends StudentBuilder you'd want it to return something else entirely... Is that doable? Yes, with generics. However, it's ugly as hell and introduces quite a bit of complexity. Therefore, I refuse to post the code that illustrates it, for the fear that someone will see this thread and actually use it in their software.
You might think rearranging method calls will work (calling id before calling name): new StudentBuilder().id(165).name("Jane Doe").build(), but it won't. At least not without an explicit cast to Student: (Student)new StudentBuilder().id(165).name("Jane Doe").build() since, in this case, PersonBuilder#build is being called which has a return type of Person... This is simply unacceptable! Even if it worked without an explicit cast, it should make you wince to know that a builder's methods must be called in a certain order. Because if you don't, something won't work...
There are many more problems that would arise if you continue trying to get it to work. And even if you did get it to work, I don't think it would be easily comprehensible and certainly not elegant. Of course, feel free to prove me wrong and post your solution here.
By the way, you should also ask yourself what is an abstract builder? Because, it sounds like an oxymoron.
In the end, I believe that the scope of this question is too great. The answer is domain-specific and hard to come up with in the absence of your requirements. Just remember, the general guideline for builders is to have them be as simple as possible.
Also, take a look at a related question.
As far as I can tell if you remove the generics then
BaseThingBuilder<Thing> builder =
new ThingBuilder("Required!", "Base Required!")
changes to
BaseThingBuilder builder =
new ThingBuilder("Required!", "Base Required!")
The rest of it all remains same, including the restriction that subclass has to be initialized first. So I really don't think this warrants use of generics. Maybe I am missing something.
I seem to remember something like this from Bjarne Stroustrup, long back...
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