Abstract method implementation that does nothing - java

I'm not quite sure how to word this question, but hopefully the example will make it a bit more clear. I'm trying to figure out the best way to have one of the implemented abstract methods not be called (do nothing) and I'm curious if my current approach is at all somewhat right.
abstract class Vehicle {
void doSomething() {
if (this.getClass() instanceof Chevy) {
operateOnCar();
}
}
abstract void operateOnCar();
}
class Chevy extends Vehicle {
#Override
void operateOnCar() {
print("Doing something to a car")
}
}
class HarleyDavidson extends Vehicle {
#Override
void operateOnCar() {
throw Exception("This isn't a car")
}
}
The other approach I can think of is to have the HarleyDavidson class implement operateOnCar()but do absolutely nothing - i.e. an empty method body. Is that potentially better? Maybe neither of these are viable examples and I should reconsider my design. Thanks!
Edit: tried to make my example a bit more clear

I'm trying to figure out the best way to have one of the implemented
abstract methods not be called (do nothing)
Asserting that a method should not be called is totally different from asserting that it should do nothing. It is furthermore wrongheaded to define a method on the superclass, regardless of abstractness, that is not ok to call on any instance of any subclass. Thus, some variation on the "do nothing" alternative is a much better choice.
And what's so hard about a method doing nothing when it does not need even to provide a return value? This is a method that does nothing:
void isCar() {
// empty
}
I should also observe at this point a method named isCar would be expected by most Java programmers to return a boolean indicating whether the object on which it is invoked is a "car", whatever that means in context. It would come as a surprise that such a method is declared not to return anything, and perhaps an even bigger surprise that it writes to System.out.

You're blurring the responsibilities of your abstract class and its concrete implementations. This is evidenced by your doSomething method.
void doSomething() {
if (this.getClass() instanceof Chevy) {
operateOnCar();
}
}
Your abstract class shouldn't care what instance it is; only the Chevy class needs to do something with this.
This may be why you're getting mixed up with the operateOnCar method. A Car is a Vehicle, but not all Vehicles are Cars. You could have trucks, vans, locomotives, boats, planes...all of which are vehicles in their own right, but definitely wouldn't support an operateOnCar method.
It may be as simple as renaming your method. You can definitely operate or fix a vehicle. You just want to keep that as agnostic as possible at the higher levels of the inheritance chain.

If you make a class, than that class (including its derived classes) should only have properties/methods related to that class. If a property/method does not fit, it shouldn't be in a class.
So how you can put OperateOnCar somewhere: with the strategy pattern, which is a common design pattern.
Than you make an interface OperatableOnVehicle, with an operation OperateOnVehicle. For vehicle it will be implemented, for a HarleyDavidson it is not implemented.
Try to avoid to use the word 'car'.
There are many examples to be found on internet about the strategy pattern, so google for more information about it's background.

I think if object calling this method throws the following exception:
throw Exception("This method should only be called if the car is a chevy")
There would be better to print out that it's not a car. As the name of the method suggests, it should return boolean
Is Chevy a car? Yes it is - return true and inform about the result
Is HarleyDavidson a car? No, it is not - return false and inform as well
is for exampleBicycle a car? No, definitely not. Is it a vehicle? Yes. Is legitime to ask it whether it's a car? Why not?
By the way, have you considered the following hierarchy?
Vehicle <- Car <- Chevy
Vehicle <- (Motocycle ) <- HarleyDavidson

Related

Why do we need abstract methods?

I have been studying abstract methods lately and I can't understand why do we need them?
I mean, after all, we are just overriding them. Do you know its just a declaration? Why do we need them?
Also, I tried understanding this from the internet and everywhere there's an explanation like imagine there's an abstract class human then there're its subclasses disabled and not disabled then the abstract function in human class walking() will contain different body or code. Now what I am saying is why don't we just create a function in the disabled and not disabled subclasses instead of overriding. Thus again back to the question in the first paragraph. Please explain it.
One of the most obvious uses of abstract methods is letting the abstract class call them from an implementation of other methods.
Here is an example:
class AbstractToy {
protected abstract String getName();
protected abstract String getSize();
public String getDescription() {
return "This is a really "+getSize()+" "+getName();
}
}
class ToyBear extends AbstractToy {
protected override String getName() { return "bear"; }
protected override String getSize() { return "big"; }
}
class ToyPenguin extends AbstractToy {
protected override String getName() { return "penguin"; }
protected override String getSize() { return "tiny"; }
}
Note how AbstractToy's implementation of getDescription is able to call getName and getSize, even though the definitions are in the subclasses. This is an instance of a well-known design pattern called Template Method.
The abstract method definition in a base type is a contract that guarantees that every concrete implementation of that type will have an implementation of that method.
Without it, the compiler wouldn't allow you to call that method on a reference of the base-type, because it couldn't guarantee that such a method will always be there.
So if you have
MyBaseClass x = getAnInstance();
x.doTheThing();
and MyBaseClass doesn't have a doTheThing method, then the compiler will tell you that it can't let you do that. By adding an abstract doTheThing method you guarantee that every concrete implementation that getAnInstance() can return has an implementation, which is good enough for the compiler, so it'll let you call that method.
Basically a more fundamental truth, that needs to be groked first is this:
You will have instances where the type of the variable is more general than the type of the value it holds. In simple cases you can just make the variable be the specific type:
MyDerivedClassA a = new MyDerivcedClassA();
In that case you could obviously call any method of MyDerivedClassA and wouldn't need any abstract methods in the base class.
But sometimes you want to do a thing with any MyBaseClass instance and you don't know what specific type it is:
public void doTheThingsForAll(Collection<? extends MyBaseClass> baseClassReferences) {
for (MyBaseClass myBaseReference : baseClassReferences) {
myBaseReference.doTheThing();
}
}
If your MyBaseClass didn't have the doTheThing abstract method, then the compiler wouldn't let you do that.
To continue with your example, at some point you might have a List of humans, and you don't really care whether they are disabled or not, all you care about is that you want to call the walking() method on them. In order to do that, the Human class needs to define a walking() method. However, you might not know how to implement that without knowing whether the human is or isn't disabled. So you leave the implementation to the inheriting classes.
There are some examples of how you'd use this in the other answers, so let me give some explanation of why you might do this.
First, one common rule of Object Oriented Design is that you should, in general, try to program to interfaces rather than specific implementations. This tends to improve the program's flexibility and maintainability if you need to change some behavior later. For example, in one program I wrote, we were writing data to CSV files. We later decided to switch to writing to Excel files instead. Programming to interfaces (rather than a specific implementation) made it a lot easier for us to make this change because we could just "drop in" a new class to write to Excel files in place of the class to write to CSV files.
You probably haven't studied this yet, but this is actually important for certain design patterns. A few notable examples of where this is potentially helpful are the Factory Pattern, the Strategy Pattern, and the State Pattern.
For context, a Design Pattern is a standard way of describing and documenting a solution to a known problem. If, for example, someone says "you should use the strategy pattern to solve this problem," this makes the general idea of how you should approach the problem clear.
Because sometimes we need a method that should behave differently in its instances.
For example, imagine a class Animal which contains a method Shout.
We are going to have different instances of this Animal class but we need to implement the method differently in some cases like below:
class Animal:
/**
different properties and methods
which are shared between all animals here
*/
...
method shout():
pass
class Dog extends Animal:
method shout():
makeDogVoice()
class Cat extends Animal:
method shout():
makeCatVoice()
dog = new Animal
cat = new Animal
dog.shout()
cat.shout()
So dog shouts like dogs, and cat shouts like cats! Without implementing the shared behaviors twice
There is a different behavior of shouting in these instances. So we need abstract classes.
Suppose you don't know about implementation and still want to declare a method then we can do that with the help of abstract modifier and making it an abstract method. For abstract method only declaration is available but not the implementation. Hence they should end with ;
Example:
public abstract void m1(); // this is correct
public abstract void m1(){ ... } // this is wrong
Advantage: By declaring abstract method in parent class we can provide guideline to child classes such that which methods are compulsory to implement.
Example:
abstract class Vehicle{
abstract int getNoOfWheels();
}
Class Bus extends Car{
public int getNoOfWheels(){
return 4;
}
}
If you want the short answer, think of this:
You have an abstract class Car.
You implement 2 classes that extend it, Ferrari and Mercedes.
Now:
What if you did one of the following, for the method drive(), common to all cars:
1) changed the visibility of the method,
2) changed the name of the method from driving to Driving,
3) changed the return type, from a boolean to an int
Think about it. It might not seem to make any difference right, because they are different implementations?
Wrong!
If I am iterating through an array of cars, I would have to call a different method for each type of car, thereby making this implementation of abstract useless.
Abstract classes are there to group classes with a common template, that share common properties. One way this helps would be the looping over the array:
Abstract methods ensure that all cars declare the same method,
and therefore, any object of a subclass of Car will have the method drive(), as defined in the abstract class, making the for loop mentioned easy to implement.
Hope this helps.

Understanding Java Interfaces Principles

I am reading a Java book and stuck again this time thinking about what this whole paragraph actually means:
Interfaces are designed to support dynamic method resolution at run time. Normally, in order for a method to be called from one class to another, both classes need to be present at compile time so the Java compiler can check to ensure that the method signatures are compatible. This requirement by itself makes for a static and nonextensible classing environment. Inevitably in a system like this, functionality gets pushed up higher and higher in the class hierarchy so that the mechanisms will be available to more and more subclasses. Interfaces are designed to avoid this problem. They disconnect the definition of a method or set of methods from the inheritance hierarchy. Since interfaces are in a different hierarchy from classes, it is possible for classes that are unrelated in terms of the class hierarchy to implement the same interface. This is where the real power of interfaces is realized.
First question: what does the author mean by saying from one class to another? Does he mean that those classes are related in terms of the hierarchy? I mean, assigning subclass object reference to its superclass type variable and then calling a method?
Second question: what does the author again mean by saying This requirement by itself makes for a static and nonextensible classing environment? I don't understand the makes for meaning (english is not my main language) and why the environment is called static and nonextensible.
Third question: what does he mean by saying functionality gets pushed up higher and higher? Why does it get pushed up higher and higher? What functionality? Also, mechanisms will be available to more and more subclasses. What mechanisms? Methods?
Fourth question: Interfaces are designed to avoid this problem. What problem???
I know the answers must be obvious but I don't know them. Maybe mainly because I don't undestand some magic english phrases. Please help me to understand what is this whole paragraph telling.
Between any two classes. If your code contains a call to String.substring() for example, the String class and its substring() method must be available at compile time.
As said, "makes for" means the same as "creates". The environment is non-extensible because everything you may want to use must be available at compile time. (This isn't 100% true though. Abstract classes and methods provide extension points even when no interfaces are present, but they aren't very flexible as we're going to see.)
Imagine that you have two classes: Foo and Bar. Both classes extend the class Thingy. But then you want to add a new functionality, let's say you want to display both in HTML on a web page. So you add a method to both that does that.
The basic problem
abstract class Thingy { ... }
class Foo extends Thingy {
...
public String toHTMLString() {
...
}
}
class Bar extends Thingy {
...
public String toHTMLString() {
...
}
}
This is great but how do you call this method?
public String createWebPage( Thingy th ) {
...
if (th instanceof Foo)
return ((Foo)th).toHTMLString();
if (th instanceof Bar)
return ((Bar)th).toHTMLString();
...
}
Clearly this way isn't flexible at all. So what can you do? Well, you can push toHTMLString() up into their common ancestor, Thingy. (And this is what the book is talking about.)
A naive attempt to resolve it
abstract class Thingy {
...
public abstract String toHTMLString();
}
class Foo extends Thingy {
...
public String toHTMLString() {
...
}
}
class Bar extends Thingy {
...
public String toHTMLString() {
...
}
}
And then you can call it like this:
public String createWebPage( Thingy th ) {
...
return th.toHTMLString();
}
Success! Except now you've forced every class extending Thingy to implement a toHTMLString() method, even if it doesn't make sense for some of them. Even worse, what if the two objects do not extend anything explicitly, they're completely unrelated? You'd have to push the method up all the way into their common ancestor, which is java.lang.Object. And you can't do that.
Solution with interfaces
So what can we do with interfaces?
abstract class Thingy { ... }
interface HTMLPrintable {
public String toHTMLString();
}
class Foo extends Thingy implements HTMLPrintable {
...
public String toHTMLString() {
...
}
}
class Bar extends Thingy implements HTMLPrintable {
...
public String toHTMLString() {
...
}
}
//We've added another class that isn't related to all of the above but is still HTMLPrintable,
//with interfaces we can do this.
class NotEvenAThingy implements HTMLPrintable {
public String toHTMLString() {
...
}
}
And the calling code will be simply
public String createWebPage( HTMLPrintable th ) {
...
return th.toHTMLString(); // "implements HTMLPrintable" guarantees that this method exists
}
What are interfaces then?
There are many metaphors used to understand interfaces, the most popular is probably the idea of a contract. What it says to the caller is this: "If you need X done, we'll get it done. Don't worry about how, that's not your problem." (Although the word "contract" is often used in a more general sense, so be careful.)
Or in another way: if you want to buy a newspaper, you don't care if it's sold in a supermarket, a newsagents or a small stall in the street, you just want to buy a newspaper. So NewspaperVendor in this case is an interface with one method: sellNewsPaper(). And if someone later decides to sell newspaper online or door-to-door, all they need to do is implement the interface and people will buy from them.
But my favourite example is the little sticker in shop windows that says "we accept X,Y and Z credit cards". That's the purest real-world example of an interface. The shops could sell anything (they may not even be shops, some might be restaurants), the card readers they use are different too. But you don't care about all of that, you look at the sign and you know you can pay with your card there.
The Key to paragraph is "classes need to be present at compile time" in line 2. Classes are more concrete. While interfaces are abstract.
As classes are concrete so Designer and programmer needs to know all about class structure and how the methods are implemented. Where as interfaces are more abstract. (They contain abstract methods only). So programmer needs to know only what methods an interface has to have and signature of those methods. He does not need to know detail how these are implemented.
Thus using interfaces is easier and better while making subclasses. You only need to know method signatures of interface.
Using concrete class we have to implement functionality of a method high in class hierarchy while using interface avoids this problem. (There is a related concept of polymorphism that you would probably learn later)

Mock any method signature with Mockito

Hi I have this piece of code that is not very well designed, but I'm not the owner of this code so I can't change it.
public interface Car{ // This is a marker interface. }
public class BigCar implements Car{
public boolean isVeryBig(){
return true;}
}
public class QuiteBigCar implements Car{
public boolean isVeryBig(boolean withHatchBack){
return true;}
}
public Pickup implements Car{
public boolean isVeryBig(boolean withHatchBack, boolean withRoofRack){
return true;}
}
You see the interface only exists to let me know that BigCar, QuiteBigCar and Pickup "is a" Car. Not very clever, but that's what I have to deal with.
Now I have a method that receives a Car as a param and will returned a mocked version of the car. I want the mock to make sure every time isVeryBig() is called, it will return false regardless of the method signature. The problem is I don't have a common interface for all isVeryBig() methods; they all have a different signature.
public Car mockMyCar(Car car){
Car mockedCar = mock(car);
when(mockedCar.isVeryBig()) <-- This wont work since the method doesn't exist on the interface
return mockedCar;
}
Yes, I could cast Car into their subclass but this is not an option for me as there is too many classes that implement Car, make a instanceOf check on all implementation would make the code very nasty and I don't control new implementations of Car in the future.
Any idea?
A few options, in order from least-hacky to most-hacky:
Acknowledge that mocking a Car here makes as little sense as mocking a Serializable, and that you should actually pick an implementation to mock. You won't have the same trouble mocking a concrete BigCar or Pickup, and you can run through a few different implementations in a few test cases.
Refactor to a common properly-polymorphic interface as TrustNoOne described, rather than using ersatz polymorphism the way you have here. I know you may have your hands tied, but whoever stumbles across this question next might not.
You can do something similar to what you're describing—matching methods by name instead of signature—by supplying a default Answer when you create the mock:
Car car = Mockito.mock(Car.class, new Answer<Object>() {
#Override public Object answer(InvocationOnMock invocation) {
if (invocation.getMethod().getName().equals("isVeryBig")) {
return false;
}
// Delegate to the default answer.
return Mockito.RETURNS_DEFAULTS.answer(invocation);
}
};
Bear in mind, though, that your particular situation (of being able to downcast to one of a variety of implementations with different signatures) may require use of the extraInterfaces feature to let Java downcast as needed, which makes this entire thing tricky and fragile. You'd probably be better off using one of the other above solutions instead.

What is the proper design to deal with this?

I'm working on a legacy Java application, that deals with "fruits" and "vegetables", let's say, for the sake of the question.
They are treated as different things internally, cause they don't have all methods/properties in common, but a lot of things are DONE very similar to both of them.
So, we have a ton of methods doSomethingWithAFruit(Fruit f) and doSomethingWithAVegetable(Veg v), that use the proper doOtherStuffWithAFruit(Fruit f) / doOtherStuffWithAVeg(Veg v). And those are very similar, except that methods that do things with fruits only call the methods that do things with fruits, and the same thing for vegetables.
I want to refactor this to reduce the duplication, but I'm not sure what is the best way to accomplish that. I've read a bit about some design patterns, but I don't know if it has made any clearer to me. (I can recognize some patterns in the code I use, but I don't really know when I should be applying a pattern to improve things around. Maybe I should be reading more about refactoring itself...)
I was thinking of these two options:
1. Creating a class that can have an instance of either a Fruit or a Vegetable and pass it around to the methods, trying to minimize the duplication. It would go like this:
public void doSomething(Plant p) {
// do the stuff that is common, and then...
if (p.hasFruit()) {
doThingWithFruit(p.getFruit());
} else {
doThingWithVegetable(p.getVegetable());
}
}
This would get things a bit better, but I don't know... it still feels wrong.
2. The other alternative I thought was to put an interface in Fruit and Vegetable with the stuff that is common to them, and use that to pass it around. I feel this is the cleaner approach, although I will have to use instanceof and cast to Fruit/Vegetable when it needs stuff that is specific to them.
So, what more can I do here? And what are the shortcomings of these approaches?
UPDATE: Note that the question is a bit simplified, I'm looking for way to do things WITH the "plants", that is, code that mostly "uses" them instead of doing things TO them. Having said that, those similar methods I refer to cannot be inside the "Plants" classes, and they usually have another argument, like:
public void createSomethingUsingFruit(Something s, Fruit f);
public void createSomethingUsingVegetable(Something s, Vegetable v);
Namely, those methods have other concerns besides Fruits/Vegetables, and aren't really appropriated to be in any Fruit/Vegetable class.
UPDATE 2: Most code in those methods only reads state from the Fruit/Vegetable objects, and create instances of other classes according to the appropriate type, store in the database and so on -- from my answer to a question in the comments that I think it's important.
I think the 2nd approach would be better.. Designing to an interface is always a better way to design.. That way you can switch between your implementation easily..
And if you use interfaces, you won't need to do typecast as you can easily exploit the concept of polymorphism.. That is, you will have `Base class reference pointing to a subclass object..
But if you want to keep only methods common to fruits and vegetables in your interface, and specific implementation in your implementation class.. Then in that case typecasting would be required..
So, you can have a generic method at interface level.. And more specific method at implementation level..
public interface Food {
public void eat(Food food);
}
public class Fruit implements Food {
// Can have interface reference as parameter.. But will take Fruit object
public void eat(Food food) {
/ ** Fruit specific task **/
}
}
public class Vegetable implements Food {
// Can have interface reference as parameter.. But will take Vegetable object
public void eat(Food food) {
/** Vegetable specific task **/
}
}
public class Test {
public static void main(String args[]) {
Food fruit = new Fruit();
fruit.eat(new Fruit()); // Invoke Fruit Version
Food vegetable = new Vegetable();
vegetable.eat(new Vegetable()); // Invoke vegetable version
}
}
OK, I have modified a code to make eat() method to take parameters of type Food.. That will not make much of a difference.. You can pass Vegetable object to Food reference..
Another option you can use, or perhaps include it as part of your solution, is to ask the consumer if it can manage the object that you are passing it. At this point, it becomes the consumer's responsibility to ensure it knows how to handle the object you are sending it.
For instance, if your consumer is called Eat, you would do something like:
Consumer e = new Eat();
Consumer w = new Water();
if( e.canProcess( myFruit ) )
e.doSomethingWith( myFruit );
else if ( w.canProcess( myFruit ) )
w.doSomethingWith( myFruit );
.... etc
But then you end up with a lot of it/else classes, so you create yourself a Factory which determines which consumer you want. Your Factory basically does the if/else branching to determine which consumer can handle the object you pass, and returns the consumer to you.
So it looks something like
public class Factory {
public static Consumer getConsumer( Object o ){
Consumer e = new Eat();
Consumer w = new Water();
if( e.canProcess( o ) )
return e;
else if ( w.canProcess( o ) )
return w;
}
}
Then your code becomes:
Consumer c = Factory.getConsumer( myFruit );
c.doSomethingWith( myFruit );
Of course in the canProcess method of the consumer, it would be basically an instanceof or some other function your derive to determine if it can handle your class.
public class Eat implements Consumer{
public boolean canProcess(Object o ){
return o instanceof Fruit;
}
}
So you end up shifting the responsibility from your class to a Factory class to determine which objects can be handled. The trick, of course, is that all Consumers must implement a common interface.
I realize that my pseudo-code is very basic, but it is just to point out the general idea. This may or may not work in your case and/or become overkill depending on how your classes are structured, but if well designed, can significantly improve readability of your code, and truely keep all logic for each type self-contained in their own class without instanceof and if/then scattered everywhere.
If you have functionality that is specific to fruits and vegetables respectively and a client using both types has to distinguish (using instanceof) - that is a coherence vs. coupling problem.
Maybe consider if said functionality is not better placed near fruit and vegetable themselves instead of with the client. The client may then somehow be refered to the functionality (through a generic interface) not caring what instance he is dealing with. Polymorphism would be preserved at least from the client's perspective.
But that is theoretical and may not be practical or be over-engineered for your use case. Or you could end up actually just hiding instanceof somewhere else in your design. instanceof is going to be a bad thing when you start having more inheritance siblings next to fruits and vegetables. Then you would start violating the Open Closed Principle.
I would create and abstract base class (let's say - Food, but I don't know your domain, something else might fit better) and start to migrate methods to it one after another.
In case you see that 'doSomethingWithVeg' and 'doSomthingWithFruit' are slightly different - create the 'doSomething' method at the base class and use abstract methods to do only the parts that are different (I guess the main business logic can be united, and only minor issues like write to DB/file are different).
When you have one method ready - test it. After you're sure it's ok - go to the other one. When you are done, the Fruit and Veg classes shouldn't have any methods but the implementations of the abstract ones (the tiny differences between them).
Hope it helps..
This is a basic OOD question. since fruits and vegetables are of type Plant.
I would suggest:
interface Plant {
doSomething();
}
class Vegetable {
doSomething(){
....
}
}
and the same with the fruit.
it seems to me that doOtherStuff methods should be private for the relevant class.
You can also consider having them both implement multiple interfaces instead of just one. That way you code against the most meaningful interface according the circumstances which will help avoid casting. Kind of what Comparable<T> does. It helps the methods (like the ones that sort objects), where they don't care what the objects are, the only requirement is that they have to be comparable. e.g. in your case both can implement some interfaces called Edible, then take both of them as Edible where an Edible is expected.

Verifying Objects using Java interfaces

I’m currently facing a design problem and would appreciate advice on how I could resolve it:
The problem
I will use an example to illustrate my problem note this is just an example:
Suppose you have an interface called Pass with methods listed:
public interface Pass {
public boolean hasPassedA();
public boolean hasPassedB();
public boolean hasPassedC();
}
Suppose you have a class which implement this interface called Assessor:
public class Assessor implements Pass{
// how should I implement this class ??
}
Finally Student class:
public class Student {
// some code that defines student behaviour not important.
}
The question is then how can I make the interaction between the Assessor and the student object a lot more flexible?
What I noticed is that an Assessor object should be something that is abstract because in reality there is no such thing as an Assessor, but instead you have different types of assessors such as a Math Assessor or English Assessor etc, which in turn will allow me to create different types of Assessor objects e.g.
MathAssessor extends Assessor
EnglishAssessor extends Assessor
The concept is that a Student can pass if all the methods declared in the Pass interface return true and all additional methods in the subjectAssessor classes return true.
What do I do in the Assessor class? I have read about adapter design patterns but haven’t fully grasped that notion or does it even apply to this situation?
To start, the Pass interface you have is not very flexible, which could make for difficulties. For example, what if one implementation of Pass only needs to have hasPassedA, or you have an implementation which needs hasPassedA, hasPassedB, hasPassedC and hasPassedD. Then the various types of assessors will need to figure out which pass conditions to check.
A more flexible way to do this might be to do something like this. Rather than having a Pass interface, maybe something like a Condition interface (the names of the classes/interfaces should be changed to make sense for your domain).
public interface Condition {
// true means the condition passed, false means it did not
boolean evalutate();
}
Now you could have a single Assessor class (I'm not sure if this is exactly how your assessor would work, but it's just a guideline):
public class Assessor {
boolean assess(Collection<Condition> conditions) {
for (Condition c : conditions) {
if (!c.evaluate()) {
return false;
}
}
// all conditions passed
return true;
}
}
Hopefully this helps for your problem.
First off, to answer your question about the adapter pattern, it doesn't apply here. You use the adapter pattern to add a layer between 2 incompatible systems to allow them to pass data back and forth.
Using your example, I would recommend writing default implementations of the hasPassed_() methods in Assessor, even if the implementation is nothing more than throwing a new UnsupportedOperationException (to answer the question about what if a particular Assessor only needs a subset of hasPassed_() methods you can just overwrite only the ones you need). You can modify the subject assessor's (e.g. MathAssessor, EnglishAssessor, etc.) Pass methods to be more specific or to provide additional checks before calling super.hasPassed_() (depending on your specific implementation).

Categories

Resources