I have a hierarchy of worker classes, all of which do some kind of processing to a workpiece. The idea is, that each worker does some pre processing, pushes the workpiece to the subclass and then does some postprocessing:
public void process(Workpiece wp) {
doPreprocessing(wp);
sub.process(wp); // this obviously doesn't work
doPostProcessing(wp);
}
Right now I'm solving this by declaring new abstract methods:
public final void process(Workpiece wp) {
doPreprocessing(wp);
subProcess(wp); // this obviously doesn't work
doPostProcessing(wp);
}
protected abstract void subProcess(Workpiece wp);
which has the obvious disadvantage that for each hierarchy-level, there is an additional, new method.
I would like to guarantee, that all pre- and post-process methods are executed even with new, user-implemented workers, which are not under my control.
How would you do that?
Following the template method pattern, you would do this by designing you class such that the doPreProcessing and doPostProcessing methods are overridden in subclasses. I'm guessing you don't want to do this, because you can't be sure the subclasses will call super, and thus you can't "guarantee that all pre- and post-process methods are executed even with new, user-implemented workers."
Instead of using inheritance, you could try a design that chains worker objects together, like this:
public abstract class Worker {
private Worker next;
protected Worker(Worker next) {
this.next = next;
}
public void process(Workpiece wp) {
preProcess(wp);
if (next != null)
next.process(wp);
postProcess(wp);
}
public abstract void preProcess(Workpiece wp);
public abstract void postProcess(Workpiece wp);
}
Your classes, and user-implemented classes, instead of extending the "next" worker, create the "next" worker in their constructors:
public class MyWorker extends Worker {
public MyWorker() {
super(new MyOtherWorker());
}
public abstract void preProcess(Workpiece wp) {
// code
}
public abstract void postProcess(Workpiece wp) {
// code
}
}
Related
I'm implementing observer pattern in the following way:
interface Layer{
void adjustString(Set<String> strings);
}
interface NotifiableLayer extends Layer{
void layerAdjusted(Layer layer);
}
abstract class ObservableLayer implements Layer{
Set<NotifiableLayer> observers = new HashSet<>();
void addObserver(NotifiableLayer layer){
observers.add(layer);
}
void removeObserver(NotifiableLayer layer){
observers.remove(layer);
}
void notifyObservers(){
observers.forEach(l -> l.layerAdjusted(this));
}
}
class MyLayer extends ObservableLayer{
#Override
public void adjustString(Set<String> strings) {
this.notifyObservers(); //can this be auto?
}
}
And this works of course, but whoever is implementing ObservableLayer needs to remember to call this.notifyObservers() in the adjustString method. This is not that of a big deal, but I wanted to see if there is a way to completely hide this.
So far, I only have this idea (using template method):
abstract class ObservableLayer implements Layer{
//...methods removed for simplicity
#Override
public void adjustString(Set<String> strings) {
this.doAdjustString(strings);
this.notifyObservers(); //<---- here is auto
}
abstract void doAdjustString(Set<String> strings);
}
class MyLayer extends ObservableLayer{
#Override
public void doAdjustString(Set<String> strings) {
//now notification is in base adjustString
}
}
but here I don't like that method name changed to doAdjustString, and it is not anymore uniform between other layer implementations (layers that directly implement Layer interface).
Is there any easy way to have this functionallity, but to keep public void adjustString(Set<String> strings) signature in MyLayer class?
One way would be to use a Decorator instance that holds an ObservableLayer instance and delegates to it.
final class LayerDecorator implements Layer {
final private ObservableLayer delegate;
public LayerDecorator(ObservableLayer delegate) {
this.delegate = delegate;
}
#Override
public void adjustString(Set<String> strings) {
delegate.adjustString(strings);
delegate.notifyObservers();
}
}
This assumes that calling code is working using references to Layer instead of ObservableLayer.
If calling code has to work using references to ObservableLayer then maybe it is better to refactor ObservableLayer to be an interface having the methods to register listeners, remove them and notify them. This interface also extends the Layer interface.
interface IObservableLayer extends Layer {
void addObserver(NotifiableLayer layer);
void removeObserver(NotifiableLayer layer);
void notifyObservers();
}
The abstract class ObservableLayer changes to implement IObservableLayer instead of Layer directly. This class remains public to support application classes to define variations of observable layers.
Next an internal decorator for observable layers can be defined as shown below.
final class ObservableLayerDecorator implements IObservableLayer {
final private ObservableLayer delegate;
public ObservableLayerDecorator(ObservableLayer delegate) {
this.delegate = delegate;
}
#Override
public void addObserver(NotifiableLayer layer) {
delegate.addObserver(layer);
}
#Override
public void removeObserver(NotifiableLayer layer) {
delegate.removeObserver(layer);
}
#Override
public void notifyObservers() {
delegate.notifyObservers();
}
#Override
public void adjustString(Set<String> strings) {
delegate.adjustString(strings);
this.notifyObservers();
}
}
Please note how the notification is done in this case.
Now instances of IObservableLayer can be created as
IObservableLayer observableLayer = new ObservableLayerDecorator(new MyClass());
Factory methods will be helpful here as they can be defined to handle creation of various application-level observable layer classes so that the instances can be created consistently that return an IObservableLayer which is decorated. That will free up developers from knowing how to use the decorator and allow the decorator to be an internal utility.
Another approach is aspect-oriented programming.
The following example uses AspectJ to intercept any public method execution on a class extending Observable, and invoke notifyObservers() on the same object.
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class EventAspect {
#AfterReturning("execution(public * Observable.*(..)) && target(observable)")
public void notifyObservers(Observable observable) {
observable.notifyObservers();
}
}
In doing some restructuring on a project of mine, I've been attempting to better utilise object oriented concepts in my code but I'm not sure how to structure this particular situation:
A method can trigger one of three possible "events", with each event having a dependency on a particular type (Player, Block, World) which needs to happen at runtime as they are deserialised from a file. In an attempt to simplify the execution path I structured it like this so they can all be part of a List which just executes a single method:
public interface IEvent {
void trigger();
}
public class PlayerEvent implements IEvent {
private Player player;
public void passPlayer(Player player){
this.player = player;
}
public void trigger(){
// player does things
}
}
public class BlockEvent implements IEvent {
private Block block;
public void passBlock(Block block){
this.block = block;
}
public void trigger(){
// block does things
}
}
However, since each event is dependent on a Player or Block depending on its type, I would have to iterate over the list and downcast each object using instanceof to pass the relevant dependency.
public void executeEvents(){
for(IEvent event : events){
if(event instanceof PlayerEvent){
((PlayerEvent) event).passPlayer(player);
} else {
((BlockEvent) event).passBlock(block);
}
event.trigger();
}
}
I read that downcasting should never be done under any circumstances, so I've been wondering what alternatives I could use that would follow a similar simple execution path but falls under good OOP practice? Or should I just eliminate the interface altogether and have a separate List for each event type?
I read that downcasting should never be done under any circumstances,
so I've been wondering what alternatives
I would not generalize. Applications/libraries that generate code or use reflection generally may use downcast.
In other cases, downcast should indeed be avoided.
You have multiple ways to achieve your goals without downcasting.
1) Don't manipulate a too broad type in the List. Additionally you could make IEvent a generic interface and generalize passPlayer() and passBlock() in pass() that you will move up in the interface.
The interface could look like :
public interface IEvent<T> {
void trigger();
void pass(T t);
}
And implementation of it could look like :
public class PlayerEvent implements IEvent<Player> {
private Player player;
public void trigger() {
// player does things
}
#Override
public void pass(Player t) {
}
}
Now with a more specific typed List you could write :
private Player player = ...;
public void executeEvents() {
List<IEvent<Player>> events = ...;
for (IEvent<Player> event : events) {
event.pass(player);
}
}
2) Use the visitor pattern to benefit from a double dispatch.
Event -> Visitor -> processing.
Each pass() method become a method of the Visitor.
You could enrich the IEvent interface to add an accept() method that accepts a Visitor :
public interface IEvent {
void trigger();
void accept(Visitor visitor);
}
Here the Visitor interface and implementation :
Visitor interface
public interface Visitor {
void visitBlockEvent(BlockEvent block);
void visitPlayerEvent(PlayerEvent player);
}
Visitor implementation
public class ProcessEventVisitor implements Visitor {
private Player player;
private Block block;
#Override
public void visitBlockEvent(BlockEvent blockEvent) {
// do your processing
}
#Override
public void visitPlayerEvent(PlayerEvent playerEvent) {
// do your processing
}
}
IEvent subclasses delegate now to the Visitor parameter the processing :
public class PlayerEvent implements IEvent{
public void trigger() {
// player does things
}
#Override
public void accept(Visitor visitor) {
visitor.visitPlayerEvent(this);
}
}
And the client code can now look like :
private Player player;
public void executeEvents() {
List<IEvent> events = ...;
ProcessEventVisitor visitor = new ProcessEventVisitor();
for (IEvent event : events) {
event.accept(visitor);
}
}
I have 2 classes Workflow1.java and Workflow2.java. At a class Selection.java I want to be able to choose between instantiating one of the 2 classes as a static member however I cannot implement the factory pattern as Workflow1 and Workflow2 cannot be subclasses since their methods are not the same. Although they achieve the same end result they do so by doing entirely different operations. Is there a design pattern for this scenario?
Example: If the classes were WalkHelper.java and DriveHelper.java, the methods you need in each are entirely different but what you are trying to achieve is the same - reach a destination. I haven't created walk() and drive() as methods as WalkHelper.java has existed in our code base and I'm adding DriveHelper.java to it.
It sounds like you can still use a Factory pattern but you may have to use an Adaptor to make them equal... Without knowing more, it's a pretty difficult question to answer.
interface IFactory {
void run();
String getResult();
}
class Workflow1Adapter implements IFactory {
Workflow1 wf1 = new Workflow1();
public void run() {
wf1.doSomething();
}
public String getResult() {
wf1.doAnother();
}
}
class Workflow2Adapter implements IFactory {
Workflow2 wf2 = new Workflow2();
public void run() {
wf2.doThatThing();
}
public String getResult() {
wf2.doReturn();
}
}
class Workflow1 {
public void doSomething() {}
public String doAnother() {}
}
class Workflow2 {
public void doThatThing() {}
public String doReturn() {}
}
I have a number of classes that define a method, and I want to execute some code (say, some "prologue" and "epilogue") around that method:
public interface Thing {
public void stuff();
public void callStuff();
}
public abstract class Something implements Thing {
public abstract void stuff();
public void callStuff() {
... // common prologue
//try {
stuff();
//} finally {
... // common epilogue
//}
}
}
public class A extends Something {
public void stuff() { ... }
}
public class B extends Something {
public void stuff() { ... }
}
public class Wrapper extends Thing {
private Thing t;
Wrapper(Thing thing) { t = thing; }
public void stuff() { t.stuff(); }
public void callStuff() { t.callStuff(); }
}
// Use:
Something s = ...;
s.callStuff();
You see that the idea is that subclasses will redefine stuff() while the clients will invoke callStuff(). Nevertheless, in some rare cases one has to call stuff(), see Wrapper above.
Something like that we see in the Thread class (since JDK 1.0), child classes redefine run() but the clients invoke start().
How do I prevent clients from calling stuff() directly?
EDIT
protected does not work here because the "clients" really are children of Something coded by another team. #Deprecated would work, but stuff() is not really deprecated, and everyone knows what "deprecated" is, so I cannot redefine the meaning of #Deprecated.
Ideally, the compilation should fail unless an explicit directive is given to ignore the problem.
In Wikipedia sample and in GoF book, usage of Visitor pattern is started by calling accept method on some acceptor. But why is it this way? Why can't we start calling visit method with desired acceptor as an argument? We can still make visitor behavior depend on 2 types -- of visitor and of acceptor (double dispatch) -- and we can eliminate redundant call (as it seems to me).
Here's sample code to illustrate this:
public interface Visitor {
void visit(AcceptorA acceptor);
void visit(AcceptorB acceptor);
}
//
// Visitor which sings
//
class SingingVisitor implements Visitor {
public void visit(AcceptorA acceptor) {
System.out.println("sing A");
}
public void visit(AcceptorB acceptor) {
System.out.println("sing B");
}
}
//
// Visitor which talks
//
class TalkingVisitor implements Visitor {
public void visit(AcceptorA acceptor) {
System.out.println("talk A");
}
public void visit(AcceptorB acceptor) {
System.out.println("talk B");
}
}
//
// Acceptor subclasses
//
class AcceptorA implements BaseAcceptor {
}
class AcceptorB implements BaseAcceptor {
}
//
// Launcher class
//
class VisitorMain {
public static void main(String[] args) {
Visitor v = new TalkingVisitor();
AcceptorA a = new AcceptorA();
AcceptorB b = new AcceptorB();
v.visit(a);
v.visit(b);
v = new SingingVisitor();
v.visit(a);
v.visit(b);
}
}
Consider:
class House implements HouseAcceptor {
HouseAcceptor kitchen;
HouseAcceptor livingRoom;
void accept(HouseVisitor visitor) {
visitor.visit(this);
kitchen.accept(visitor);
livingRoom.accept(visitor);
}
}
class Kitchen implements HouseAcceptor {
void accept(HouseVisitor visitor) {
visitor.visit(this);
}
}
class LivingRoom implements HouseAcceptor {
void accept(HouseVisitor visitor) {
visitor.visit(this);
}
}
class SpeakingHouseVisitor implements HouseVisitor {
void visit(HouseAcceptor acceptor) {
System.out.println("Inside a HouseAcceptor");
}
void visit(House acceptor) {
System.out.println("Inside a House");
}
void visit(Kitchen acceptor) {
System.out.println("Inside a Kitchen");
}
void visit(LivingRoom acceptor) {
System.out.println("Inside a LivingRoom");
}
}
...
HouseAcceptor acceptor = new House();
HouseVisitor visitor = new SpeakingHouseVisitor();
...
// Doing it your way
visitor.visit(acceptor);
// Output: Inside a HouseAcceptor
// Doing it the right way
acceptor.accept(visitor);
// Output:
// Inside a House
// Inside a Kitchen
// Inside a LivingRoom
Note that if you do it your way, the runtime type of your acceptor will not make a difference: the static type will be used. By doing double dispatch you ensure that both runtime types are used.
Using your version, the following will not compile:
List<BaseAcceptor> list = ...
for(BaseAcceptor ba: list)
vi.visit(ba)
The java compiler cannot determine (statically) what ba will be, so it cannot decide at compile time which visit method to call. You would need to write an additional method:
public void visit(BaseAcceptor ba){
if(ba instanceof AcceptorA)
visit((AcceptorA)ba);
else if(ba instanceof AcceptorB)
visit((AcceptorB)ba);
}
This is not necessary using the visitor pattern.
Because Visitors have no knowledge of how to navigate the private internal fields of a composed Object.
If you called Visitor.visit(something) then it would have to figure out if that something had private fields which needed transversal. To do that, you need that something to accept your Visitor. Once you decide that navigation must be in the visited objects (and not the Visitor), then you realize that you need a call back to the Visitor to tell it what the next element in the navigation path is. Typically that's the accept(...) method; however, if you attempted to make accept(...) just a wrapper to initiate navigation (by delegation to the parameter), then you need a second set of methods to tell the Visitor you're entering X now, your entering Y now.
By using the GOF approach, one can safely subclass an item being visited and modify the visiting path to include or skip additional fields. This would not impact the existing Visitors because their interface would not change. One wouldn't need to recompile subclasses of the Visitor either.
By using your suggested approach, when one added a new type into the hierarchy of to-be-visited items, one would then need to recompile all the visitors, even the visitors had no interest in the new type.
A good compromise would be:
public interface Visitable {
public void accept(Visitor v);
}
were all your "data hierarchy" implements Visitable, and your Visitor has a "convenience method" like so
public abstract class Visitor {
public void initiate(Visitable v) {
v.accept(this);
}
public abstract void accept(...);
public abstract void accept(...);
public abstract void accept(...);
}
But it's up to you if having an interface is preferable to such a base class. To me I'd favor the more loosely coupled interface, but opinions differ.
you have no double dispatch. accept usually takes an abstract visitor as an argument.