Problem with super & overriding - better way to do this? - java

I'm having a problem in relation to using super and overriding. Basically, class B which extends A has a setter for the current state of the class. Inside the setter, depending on the value of the current state, a different event can be executed.
In the setter for B the first thing that happens is that it called super so that the setter for A can go launch general events. Then the control returns to the setter of B where I can execute specific events if needed.
The problem comes when A executes events that call the setter and so it can go multiple depths before returning back to to B.
The following code illustrates what I'm talking about (it's groovy, but that's irrelevant):
class A
{
public int num = 0;
public void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFoo( num );
}
}
class B extends A
{
public void setFoo( int i )
{
println "B: $i - num $num";
super.setFoo( i );
println "After super for $i - num: $num";
}
}
def B = new B();
B.foo = 0;
This results in an output of:
B: 0 - num 0
A: 0
B: 1 - num 1
A: 1
B: 2 - num 2
A: 2
B: 3 - num 3
A: 3
After super for 3 - num: 4
After super for 2 - num: 4
After super for 1 - num: 4
After super for 0 - num: 4
When I come back to B after the call to super ("After super for...") the value of num is always the same, meaning that it screws with what I'm trying to do in B (i.e. launch specific events).
Some points on the architecture to begin with:
"Why not use i instead of num in the setter for B"? - This is just the easiest example to show the problem - what's actually happening in my code is different, just the same problem. In my case, I have access to num, not i. Even if I rewrote part of it to pass i, the state of the class will have moved on (due to the base class)
It's a server environment, so I don't have access to a frame loop or something similar. It's event based.
It should be possible to async execute the event, or set the event up to schedule later, but that requires a lot of advance knowledge of where and when the event is going to be used, which breaks the whole point of events in the first place
What I'm looking for is a way to launch events based on the state of the class, but have it happen after the return from super (while still working for the base class) if that makes any sense.
Ideas?
EDIT
To give a better idea of the code I'm using (based on Don's suggestion to use a callback), here is a simplified version of what I have. (If you want to run it, you can just copy it into http://groovyconsole.appspot.com/):
// A is our base class
​class A{
public int currentState= 0;
public void setCurrentState( int i )
{
this.currentState = i;
this._onStateChanged();
}
protected void _onStateChanged()
{
println "The state in A is $currentState";
// depending on the state launch some events.
// these can changed the current state of
// B
if( this.currentState == 0 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
protected void _onStateChanged()
{
println "The state in B is $currentState";
super._onStateChanged();
println "The state in B afterwards is $currentState";
// launch specific events based on the current state
if( this.currentState == 0 )
println "Launch a specific event!";
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;​
B has to call super as there are some states where I want a basic plus a specific event. Basic events are normally used to set the program state, while specific ones are there to react.
In this example, my output is:
The state in B is 0
The state in A is 0
The state in B is 1
The state in A is 1
The state in B afterwards is 1
The state in B afterwards is 1
i.e. B never gets to react to the state being 0
Edit
If I change the super() call in B to the end of _onStateChanged() rather than the start, this will give the chance for it to react to the state before it gets changed. Is this a simple solution to this problem, or just wrong?
Edit
So I came up with this (again, you can copy it into the groovy console appspot site):
// A is our base class
class A{
public int currentState = 0;
public int nextState = 0;
public boolean canChange = true;
public void setCurrentState( int i )
{
if( this.canChange )
{
this.currentState = i;
this._onStateChanged();
}
else
this.nextState = i;
}
protected void _onStateChanged()
{
println "The state in A is $currentState";
// depending on the state launch some events.
// these can changed the current state of
// B
if( this.currentState == 0 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
protected void _onStateChanged()
{
this.canChange = false;
println "The state in B is $currentState";
super._onStateChanged();
println "The state in B afterwards is $currentState";
// launch specific events based on the current state
if( this.currentState == 0 )
println "Launch a specific event!";
this.canChange = true;
if( this.nextState != 0 )
{
int state = this.nextState;
this.nextState = 0;
this.currentState = state;
}
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;​
It gives me the desired output:
The state in B is 0
The state in A is 0
The state in B afterwards is 0
Launch a specific event!
The state in B is 1
The state in A is 1
The state in B afterwards is 1
but is kind of ugly. Better way?

Fundamentally, A.setFoo is broken
class A
{
public int num = 0;
public void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFoo( num );
}
}
Because new A().setFoo(2) (for example) will cause a stack overflow. Something like the following might be a better design
abstract class A
{
public int num = 0;
abstract void setFooCallback(int i)
public final void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFooCallback( num );
}
}
class B extends A
{
public void setFooCallback( int i )
{
// Implement me to launch custom events or whatever
// If you call setFoo in here you'll get a stack overflow
}
}
If you need to instantiate instances of A, just remove the abstract modifiers and change setFooCallback to:
void setFooCallback(int i) { // default implementation does nothing }
FYI, I think the above is an example of the Template (Method) pattern

The actual problem is that Java copies and passes all arguments by value. With primitives (like the int i), this results in each method getting it's own copy of the value. Usually, this is to protect against what you're actually trying to do, as method side-effects can otherwise surprise people.
A quick and easy way to fix this is to return the modified value of i - so, your call looks like this: i = super.foo(i);. This has two benefits - 1) it lets people know that you expect that the value of i may change, and 2) you're not depending on a side-effect to change the value.
Otherwise, you could change i to be some sort of object wrapper (I hesitate to say Integer, because there are some under-the-cover optimization things that could mess this design up). But if you do that, document the desired behaviour out the wazoo, or developers who use the method may be surprised at changing values (or future maintainers may not correctly adjust the values).
EDIT:
Okay, from the sound of it, you want to react to both the current and a previous state, but you never store the previous state...
Clearly, you're going to have to store off the previous state somehow - a local variable inside b._onStateChanged() is probably your best bet. Otherwise, your program will continue to react to the current state (just, the current state isn't what you were expecting).
Also, you may want to change up your architecture a little - as it is, you never know if your default behaviour (inside of A) will still be carried out. Look at #Don's recommendation again, as I suspect this will be more in the direction your architecture needs to go (you always want the generic, right?). In other words, don't call the specific behaviour first - call the generic, have it perform its modifications, and have it call the specific behaviour when it's done. If necessary, you can then also have the setFoo() method call itself recursively, allowing it to call setFooCallback() for each mutated state.

I think a better way to solve this is using the Template Method design pattern.

Ok, so I have two solutions to this. This first one is the last code sample provided. It adds another parameters to check if we can change, and if so, does, otherwise it waits:
// A is our base class
class A{
public int currentState = 0;
public int nextState = 0;
public boolean canChange = true;
public void setCurrentState( int i )
{
if( this.canChange )
{
this.currentState = i;
this._onStateChanged();
}
else
this.nextState = i;
}
protected void _onStateChanged()
{
println "The state in A is $currentState";
// depending on the state launch some events.
// these can changed the current state of
// B
if( this.currentState == 0 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
protected void _onStateChanged()
{
this.canChange = false;
println "The state in B is $currentState";
super._onStateChanged();
println "The state in B afterwards is $currentState";
// launch specific events based on the current state
if( this.currentState == 0 )
println "Launch a specific event!";
this.canChange = true;
if( this.nextState != 0 )
{
int state = this.nextState;
this.nextState = 0;
this.currentState = state;
}
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;​
The second solution takes a more listener like approach. Both the base and the extending class register functions to call when the state changes:
// A is our base class
class A{
public int currentState = 0;
public def listeners = [];
public void setCurrentState( int i )
{
// call each of our listeners with the current state
this.currentState = i;
listeners.each { it( i ); }
}
public A()
{
this.addListener( this.&_onStateChanged );
}
public void addListener( def callback )
{
this.listeners.add( 0, callback );
}
protected void _onStateChanged( int state )
{
println "The state in A is $state";
// depending on the state launch some events.
// these can changed the current state of
// B
if( state == 0 || state == 1 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
public B()
{
super();
this.addListener( this.&_onBStateChanged );
}
protected void _onBStateChanged( int state )
{
println "The state in B is $state";
// launch specific events based on the current state
if( state == 0 )
println "Launch a specific event!";
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;
Both give me the output I'm looking for, though the second one is slightly broken, as it breaks the normal convention of adding listeners. Listeners are added to the start of the list, rather than the end. That'll give me an output like:
The state in B is 0
Launch a specific event!
The state in A is 0
The state in B is 1
The state in A is 1
The state in B is 2
The state in A is 2
So B gets called first, but at least they're in a good order. If I just push listeners to the list, I get:
The state in A is 0
The state in A is 1
The state in A is 2
The state in B is 2
The state in B is 1
The state in B is 0
Launch a specific event!
So B will get to react to the state being 0, but the order is reversed and by that stage, the state has changed to something else. It also breaks a bit in that it requires knowledge that B will never launch an event that will change the state, as otherwise we still have the same problem.
Out of the two, I think the first one is the best (assuming a non-rewrite of the architecture/problem). It's a bit more complicated, but doesn't require prior knowledge anywhere and the events get called in the right order.
Unless someone can suggest a better architecture for the problem, I'll go with that.

For me it looks like you are trying to execute specific B events before 'default' A events. In this case most appropriate approach for me would be executing B events first, then calling super to trigger A events.
UPDATE:
Use Template Method pattern:
​class A{
public int currentState= 0;
public void setCurrentState( int i )
{
this.currentState = i;
println "The state in A is $currentState";
// Maybe you need to split your MyEvent into two events.
// MyEventA - Does whatever required before executing special events.
def eventA = new MyEventA( this );
eventA.execute();
this._invokeSpecialEvents();
// depending on the state launch some events.
if( this.currentState == 0 )
{
// MyEventB - Does whatever required after executing special events (do actual currentState change).
def event = new MyEventB( this );
event.execute();
}
}
protected void _invokeSpecialEvents()
{
// You mentioned that cannot make A class abstract.
// This method is empty rather than abstract only for that reason.
}
}

Related

stop java thread while running [duplicate]

I have a class MPClient and MultiplayerMatch. MultiplayerMatch, in his constructor, creates a MPClient runnable thread.
To avoid data overflow, I have a boolean named "moved" in MultiplayerMatch that changes to true when the player is moving.
In the updateMatch method, if there's any player movement, "moved" changes to true, which allow MPClient to enter an if statment (inside while). This way MPClient only sends data to the server when something changes on the game.
Neverthless, when the flag is true, in MPClient that change is not registed! MPClient still "thinks" moved equals false, even after that flag changed in MultiplayerMatch, and as a consequence, nothing is sent to the server...
After a few tests, I noticed that if I run it in Debug Mode, since I have some breakpoints, that change is registered and everything works great!
Why is the boolean change only "seen" though Debug Mode? Does it have something to do with the app "running speed", since there are breakpoints?
Here's only the important part of the code:
MPClient:
public class MPClient {
static final int TIME_OUT = 5000;
Client client;
MultiPlayMatch match;
public MPClient(String name, int team, MultiPlayMatch match) {
this.match = match;
client = new Client();
client.start();
Network.registerPackets(client);
addListeners();
try {
client.connect(TIME_OUT, "127.0.0.1", Network.PORT);
} catch (IOException e) {
e.printStackTrace();
client.stop();
}
/*this comment is just to show that here is the place where the login information is sent to the server, instead of showing all the code*/
PlayerInfo playerInfo = new PlayerInfo();
Network.UpdatePlayer updatePlayer = new Network.UpdatePlayer();
updatePlayer.name = name;
updatePlayer.team = team;
while(true) {
if(match.moved) { //--> this is the variable that is always false
playerInfo.x = match.getClientPlayerX(team);
playerInfo.y = match.getClientPlayerY(team);
updatePlayer.x = playerInfo.x;
updatePlayer.y = playerInfo.y;
client.sendTCP(updatePlayer);
match.moved = false;
}
}
}
private void addListeners() {
client.addListener(new Listener.ThreadedListener(new Listener() {
#Override
public void received(Connection connection, Object object) {
if(object instanceof Network.UpdatePlayer) {
Network.UpdatePlayer updatePlayer = (Network.UpdatePlayer) object;
match.setPlayerPosition(updatePlayer.x, updatePlayer.y, updatePlayer.name, updatePlayer.team);
}
}
}));
}
}
MultiplayerMatch:
public class MultiPlayMatch extends Match {
public boolean moved;
public MultiPlayMatch(){
super(0);
Random r = new Random();
int aux = r.nextInt(2);
aux = 0;
if(aux == 0){
homeTeam = new Team("Benfica", Team.TeamState.Attacking, w);
visitorTeam = new Team("Porto", Team.TeamState.Defending, w);
} else{
homeTeam = new Team("Benfica", Team.TeamState.Defending, w);
visitorTeam = new Team("Porto", Team.TeamState.Attacking, w);
}
//homeTeam.controlPlayer(0);
numberOfPlayers = 0;
moved = false;
}
#Override
public void updateMatch(float x, float y, Rain rain, float dt) {
homeTeam.updateControlledPlayerOnline(x, y);
rain.update();
w.step(Constants.GAME_SIMULATION_SPEED, 6, 2);
if(x != 0 || y != 0) moved = true; //this is the place the variable is changed, but if it isn't in debug mode, MPClient thinks it's always false
}
public void setPlayerPosition(float x, float y, String name, int team) {
if(team == 0)
homeTeam.changePlayerPosition(x, y, name);
else
visitorTeam.changePlayerPosition(x, y, name);
}
}
volatile
This is because it is reading a cached value of match.moved variable instead of the latest. To avoid this, declare the variable as volatile
public volatile boolean moved;
Read more here
tl;dr
AtomicBoolean is a convenient alternative to volatile.
This class wraps and protects a nested primitive boolean value while ensuring proper visibility.
Instantiate:
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
Getter:
boolean x = moved.get() // Returns current value.
Setter:
moved.set( false ) // Sets a new value.
Get, then set:
boolean x = moved.getAndSet( false ) ; // Retrieves the old value before setting a new value.
AtomicBoolean
The Answer by agamagarwal is correct. You have fallen into the visibility conundrum that occurs when accessing variables across threads. One solution is the use of volatile shown there.
Another solution is the Atomic… classes bundled with Java. In this case, AtomicBoolean.
The Atomic… classes wrap a value, and add thread-safe methods for accessing and setting that value.
I often prefer using the Atomic… classes rather than volatile. One reason for this preference is that it makes quite clear and obvious to the user that we are using a protected resource across threads.
Instantiation:
public class MultiPlayMatch extends Match {
public final AtomicBoolean moved = new AtomicBoolean( false ) ;
…
Notice two things about that instantiation:
final ensures that we do not swap out one AtomicBoolean object for another. Such swapping would put us right back into the variable visibility conundrum we are trying to escape.
The AtomicBoolean object is being instantiated at the same time as this outer object (MultiPlayMatch in your case) is being instantiated. So we have ensured that an instance of AtomicBoolean exists before any access, including any access across threads. If we waited until later (“lazy” loading), then we would be falling back into that variable visibility conundrum we are trying to escape.
Getting the value:
if ( this.match.moved.get() ) { … // Returns the primitive `true` or `false` value wrapped within this `AtomicBoolean` object.
And setting the value:
this.match.moved.set( false ) ;
You may want to get the current value while also setting a value in an immediate thread-safe “atomic” (combined) operation:
boolean oldValue = this.match.moved.getAndSet( false ) ;
To learn all about concurrency in Java, see the book, Java Concurrency in Practice by Brian Goetz, et al.

Remove object from object ArrayList

I have created an object ArrayList,
private ArrayList<Object> objects;
and I am initializing it in a constructor.
public ObjectManager(Handler handler) {
this.handler = handler;
objects = new ArrayList<>();
}
This ArrayList is then painted/added it to a canvas.
public void renderObjects(Graphics g) {
handler.getObjectManager().addObject(new InstanceOfObject(handler, 1000, 1000, g));
}
The method addObject(), adds an object to the ArrayList.
public void addObject(Object e) {
objects.add(e);
}
I would like to remove this object later, by using a similar line of code,
public void removeObject(Object e) {
objects.remove(e);
}
however I do not know how to do that because I do not know how to pass in the object that is being removed. The only way I can think of passing in the object is by doing the following:
handler.getObjectManager().removeObject(new InstanceOfObject(handler, 1000, 1000, g));
I don't even know if this would work because it's removing an "new" object. And even if it does, "g" is not defined. If I define it in the constructor, I have to change many different things which results in an error (usually a NullPointerException), but even then I cannot figure out how to call this method by passing in the Graphics g parameters.
Your Question is not clear, but this might help.
The List interface implemented by ArrayList already offers a remove method. No need for you to re-invent that.
Object reference
To remove an object, keep and pass a reference to the particular object.
Dog alice = new Dog( "Alice" , "Labrador" ) ;
Dog bob = new Dog( "Bob" , "Chihuahua" ) ;
List< Dog > dogs = new ArrayList<>() ;
dogs.add( alice ) ;
dogs.add( bob ) ;
…
dogs.remove( bob ) ;
Index number
Alternatively, remember the slot (index) of the list containing the object you want to remove. Pass that zero-based index number to the remove method.
You can actually find Java's source code on the web (like https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L644), or even as src.zip in the JDK itself. So this is how remove() looks like:
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
and while the loops with the labeled breaks may look a bit esoteric, the important part is the o.equals(): if your "InstanceOfObject" class implements its own equals(), you can make the comparison work with freshly made throwaway instances too.

calling a public method of the same class twice in another public method

i have two methods in same class method1() and method2(). method 1() is to read a 'String' and extract integers from that string and method2 () is to perform a click operation. This click operation changes the 'string' which is the input of method1 () . Evreythign is working fine but my problem is
Case 1
When i am calling these two methods from another class in following way -
method1();-------- 1
method2();-------- 2
method1();---------3
i get a clear result which shows the result of line 1 is different from line 3 becuase the string was changed by line 2 BUT
Case 2
when i am calling method1() inside method2 () in the same class in the following way -
method2();{
method1();---------1
click statement of method2;
method1();---------2
}
and calling this method2(); from another class it doesnt work
line 1 and line 2 gives same result.
where i am wrong in case 2 or its not possible to call a public method of the same class twice in another public method ?? please guide.
if you need code details here it is :-
public void clickOnFaces(int n) {
ArrayList<Integer> ratingLikes = ratingLikes(n);
int likes = ratingLikes.get(0);
int total = ratingLikes.get(1);
seleniumclient.elements(Mappings.face).get(n).click();
ArrayList<Integer> updatedRatingLikes = ratingLikes(n);
int c = updatedRatingLikes.get(0);
int d = updatedRatingLikes.get(1);
}
public ArrayList ratingLikes(int n) {
seleniumactions.waitForElement(Mappings.ratingLikes);
ArrayList<Integer> likes = new ArrayList<>();
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(seleniumclient.elements(Mappings.ratingLikes).get(n).getText());
while (m.find()) {
likes.add(Integer.parseInt(m.group()));
}
return likes;
Issue is the value of 'c' and 'd' is same as 'likes' and 'total'. how ever they change when i keep only the click statement in clickonfaces() and call these mthods from different class example :
object.ratingLikes(int 0);
object.clickOnFaces(int 0);
object.ratingLikes(int 0);

Java: count number of objects created - contsructor (call to this)

Count No. of Created Object - Constructor
I want to count the number of objects I created.
class ctt
{
static int counter = 0;
public ctt()
{
this(2.3);
System.out.println("default ctt");
}
public ctt(double a)
{
System.out.println("Double ctt");
}
public ctt(int a)
{
this();
System.out.println("Int ctt");
counter++;
}
public static void main(String[] args)
{
ctt c1 = new ctt(4);
ctt c2 = new ctt();
System.out.println("No.of object created: "+counter);
}
}
In which constructor counter++ has to come. [ If I give counter++ in all construtor method, counter++ is incremented to 3 for first object creation itself. ]
ctt c1 = new ctt(4);
When I create c1 object, counter++ is incremented to 1.
ctt c2 = new ctt();
This c2 object is not getting incremented.
Can any give Solution to this problem!
You only need to increment the counter in c (double a ) . This is because it is called in c () and also in c (int a) which in turn call c () which subsequently calls c (double a)
This looks like a homework assignment, so I will answer it based on this. If I am wrong, please comment and I will update my answer:
Look at the places that actually increase the counter (there is only one) and then look at how the signature of this method/constructor is different from the others. That should help you understand what is going on.
If that still does not help, use a debugger starting from your calling code and step through your code.
Your constructor with integer as argument only has the statement to increment counter.
the statement ctt c1 = new ctt(4) this calls ctt(int a) and
the statement ctt c2 = new ctt(); --> calls ctt() which does not increments the counter.
If you need both your constructors to increment, you need to increment the counter in your ctt() constructor too. i.e the constructor that doesn't take any arguments.

configuring "plumbing" at runtime

This is kind of a design-patterns question in Java.
I am designing a java .jar file to act as a frameworks for managing and processing a certain form of data. I want the end user to be able to dictate the "plumbing" configuration, within certain constraints, in a certain way. The pieces are producers and/or consumers, and I know how to implement them, but the connections are confusing to me... here's a nonsense example that sort of parallels my application.
Suppose I have implemented these elements:
AppleTree => produces apples
ApplePieMaker => consumes apples,
produces apple pies
ApplePress =>
consumes apples, produces apple cider
AppleSave => stores apples,
apple pies, or apple cider into a
file
AppleLoad => "reconstitutes" apples, apple pies, or apple cider from a file that was produced by AppleSave
ApplePieMonitor => displays apple pies on the screen in a GUI format, as they are produced
Now I want the user to be able to specify things like:
AppleTree | ApplePress | AppleSave cider1.sav (produce apples, make them into cider, save them to a file)
AppleTree | AppleSave apple1.sav (produce apples, save them to a file)
AppleLoad apple1.sav | ApplePieMaker | ApplePieMonitor (take saved apples, make them into pies, display the results on the screen in a GUI)
(not sure how to illustrate this, but might be specified as follows)
AppleTree tree1, ApplePieMaker piemaker1 < tree1, AppleSave apples.sav < tree1, AppleSave #select(*.sav) < piemaker1, ApplePress press1 < tree1, AppleSave cider.sav < press1, ApplePieMonitor piemon1 < piemaker1
(produce apples, make them into pies and cider, save the apples, pies and cider to separate files, with the pies going to a file selected by the user at runtime and the others going to predetermine files, and also display the pies on the screen in a GUI)
So I have a rough idea of how to architect a configuration file: namely to structure the thing into elements that have at most 1 input and at most 1 output, and then for each instantiated element, name it, and if it has an input, specify the name of the element providing the input.
What I'm unclear is how to go about coupling the elements of the program when they run. Maybe the way to go is to have a number of interfaces, like AppleConsumer, ApplePieConsumer, etc. so an ApplePieMaker would implement the AppleConsumer interface (incl. method consumeApple()), and an AppleTree would implement an AppleProducer interface which can register consumers at startup, so that every time the AppleTree produces an apple, it has a list of its consumers and calls consumeApple() on each of them, which then does the right thing without the AppleTree having to know what they are doing with the apples....
Any suggestions? Does this sort of thing have a name? I'm not really that experienced in design patterns.
edit: my end users don't know and don't care about Java. They just need to be able to set up a config file (which I'm trying to make as simple as possible so I can give them some good examples) and run my program which will read the config file, construct the elements, hook them together, and go. All the elements are under my control, I don't need to support plugins, so I don't have to be super-general.
I had that problem a while ago, and it was a bit hard to specify cleanly in Java, since my input and output could be plural. However, when you are sure to have a single input and output (since a file is a specific kind of output, right?), you could try to use checked generics.
A processing step implementation (I will call that a filter) has two checked type arguments: input and output (lets for instance suppose they all extend a common interface, and for every new type you inject in the system, you will subclass that interface).
public interface Filter<Input extends Type, Output extends Type> {
public Class<Input> getInputType();
public Class<Output> getOutputType();
public void process(Input in, Output out);
}
A filter chain is then just an array of (compatible) Filters. By compatible, I intend that for each filter, its Output is the same type as its follower Input, the first filter has an Input that match your overall input type, and the last filter has an Output that matches the expected result type. This is easy to validate, in practice, since we are using checked generics.
A filter chain is thus an other (compound) filter. The compatibility of compounded filters should be checked in the constructor, and the array of compounds final. There is no accurate way to express the "chaining" property (compatibility) of the arguments of that constructors with generics, so you are going to have to do that with bare types, which is a bit unclean.
An other way to do it that gets around this limitation, at the cost of more cumbersome writing, is to change the definition of a filter like this:
public interface Filter<Input extends Type, Output extends Type> {
public Class<Input> getInputType();
public Class<Output> getOutputType();
public Output out process(Input in);
}
We will then have to define a compound filter as an imbrication of filter pairs, thus defined:
public class CompoundFilter<Input extends Type, Output extends Type>
implements Filter<Input extends Type, Output extends Type> {
private final Filter<Input extends Type, ? extends Type> l;
private final Filter<Input extends Type, ? extends Type> r;
public <Median extends Type> CompoundFilter(
Filter<Input, Median> r,
Filter<Median, Output> l
) {
this.l = l;
this.r = r;
}
#SuppressWarnings("unchecked")
public Output out process(Input in) {
// Compute l(r(in)) = (l o r) (in)
return ((Output<Input,Type>) l).process(r.process(in));
}
}
Thus, composing filters is just a matter of writing:
Filter<A,B> f1 = new FilterImpl<A,B>;;
Filter<B,C> f2 = new FilterImpl<B,C>;
// this is mathematically f2 o f1
Filter<A,C> comp = new CompoundFilter<A,C>(f1,f2);
I could not help it, I have to workout something for this.
So here it is.
You already have the idea about the apple producer/consumer so this is how I would do it.
Create three interfaces and implement as follows:
Product - Either Apple, AppleCider, ApplePie,
Producer - AppleTree, ApplePress, ApplePieMaker, AppleLoad,
Consumer - ApplePress ( consumes Apples ), ApplePieMaker ( consumes Apples ) , AppleMonitor, AppleSave.
The idea is to have a generic Product, produced by generic Producers and consumed by generic Consumers.
Once you have that, you can create the configuration file pretty much the way you describe it, and parse it to create a new instance for each element.
element1 | element2 | element3 <parameters> | element 4
In a map you create the element name and map it to the class that will create the new instance.
Let's say
map.put( "AppleTree", YouAppleTreeClass.class );
So each time you read an element in the configuration you create the instance:
for( String item: line ) {
Object o = map.get( item ).newInstance();
}
Finally you have to validate the structure of your configuration, but basically it could be like this:
The first element should be a producer
The last should be a consumer
Any intermediate should be producer-consumers
You can parse arguments needed ( file to save data for instance )
Once you have all your objects created and chained, you start producing.
There are some thing you have to workout but they're pretty easy:
Argument passing ( the file where they will be saved/loaded from)
Object re-use in different configurations ( use the same AppleTree always )
Final notes: The following code, is just an scratch, you may really consider a dependency injector to do the job, but of course it will take you a little while to learn it.
The configuration parsing should be made by hand, for the format you're using will be unique for the end-user and should be pretty simple. Still you can deliver as much complexity you want inside your jar ( using any number of frameworks you need ).
You can also take a look to the following design patterns:
Composite
Observer
Interpreter
The implementation below, is a kind of monster the these three ( I didn't compile it, just throw some code to show how the idea would look like )
I hope this helps.
/**
* Anything. An apple, cider, pie, whatever.
*/
interface Product{}
// The kinds of products.
class Apple implements Product{}
class ApplePies implements Product{}
class AppleCider implements Product{}
/**
* This indicates the class will do something.
**/
interface Producer {
// adds a consumer to the list.
public void addConsumer( Consumer c );
// removes the consumer from the list.
public void removeConsumer( Consumer c );
// let know eveytone a product has been created.
public void notifyProductCreation( Product someProduct );
// You're producer? Produce then...
public void startProduction();
}
// To avoid copy/paste all around
class AbstractProducer implements Producer {
private List<Consumer> consumers = new ArrayList<Consumer>();
// adds a consumer to the list.
public void addConsumer( Consumer c ) {
consumers.add( c );
}
// removes the consumer from the list.
public void removeConsumer( Consumer c ) {
consumers.remove( c );
}
public void notifyProductCreation( Product someProduct ) {
for( Consumer c : list ) {
c.productCreated( someProduct );
}
}
}
interface Consumer {
// Callback to know a product was created
public void productCreated( Product p );
}
class AppleTree extends AbstractProducer {
public void startProduction() {
// do something with earh, sun, water..
// and from time to time:
Product ofThisNewApple = new Apple();
notifyProductCreation( ofThisNewApple );
}
}
class ApplePieMaker extends AbstractProducer implements Consumer {
// Ok, a product was created, but
// is it the product I care?
// check first and consume after.
public void productCreated( Product p ){
// Is this the kind of product I can handle..
// well do handle
if( p instanceof Apple ) {
/// start producing pies..
}
}
public void startProduction() {
// collect the needed number of apples and then...
Product ofPie = new ApplePie();
notifyProductCreation( ofPie );
}
}
class ApplePress extends AbstractProducer implements Consumer {
// Yeap, something gots produced.
// Just handle if it is an apple
public void productCreated( Product p ) {
if( p instanceof Apple ) {
// start producing cider
}
}
public void startProduction() {
// collect the needed number of apples and then...
Product ofCiderBottle = new AppleCider();
notifyProductCreation( ofCiderBottle );
}
}
class AppleSave implements Consumer {
public void productCreated( Product p ) {
file.append( p );// any one will do.
}
}
class AppleLoad extends AbstractProducer {
public void startProduction() {
readFromFile();
}
private readFromFile() {
for( Product p : file ) {
notifyProductCreation( p );
}
}
}
class Main {
public static void main( String [] args ) {
Configuration conf = new Configuration();
List<Producer> producers conf.read();
for( Producer p : producers ) {
// fasten your seat belts....
p.startProduction();
}
}
}
/// Ahhh, pretty ugly code below this line.
// the idea is:
// Read the configuration file
// for each line split in the "|"
// for each element create a new instance
// and chain it with the next.
// producer | consumer | etc...
// Becomes....
// new Producer().addConsumer( new Consumer() );
// Return the list of create producers.
class Configuration {
List<Producer> producers
// read the file
// create the instances
// let them run.
public List<Producer> read() {
File file = new File(....
// The format is:
// producer | consumer-producer <params> | consumer
String line = uniqueLineFrom( file );
String [] parts = line.split("|");
if( parts.length == 1 ) {
System.err.println("Invalid configuration. use element | element | etc. Only one element was....");
System.exit( 1 );
}
int length = parts.length;
for( int i = 0 ; i < parts.length ; i++ ) {
Object theInstance = implementationMap.get( parts[i] ).newInstance();
validatePosition( i, length, theInstance , parts[i] );
}
List<Producer> producers = new ArrayList<Producer>();
for( int i = 0 ; i < parts.length ; i++ ) {
Object theInstance = getInstance( parts[i] );
if( not( isLast( i, length ) && isProducer( theInstance ) ) {
// the next is its consumer
Producer producer = ( Producer ) theInstance;
producer.addConsumer( ( Consumer ) getInstance( parts[i+1] ));
producers.add( producer );
}
}
return producers;
}
// creates a new instance from the implementation map.
private Object getInstance( String key ) {
return implementationMap.get( part[i] ).newInstance();
}
// validates if an element at the given position is valid or not.
// if not, prints the message and exit.
// the first element most be a producer
// the last one a consumer
// all the middle elements producer-consumer
//
private void validatePosition( int i, int length, Object theInstance, String element ) {
if( isFirst( i ) && not(isProducer(( theInstance ) ))) {
System.err.println( "Invalid configuration: " + element + " most be a producer ( either Ap...");
System.exit( 2 );
} else if ( isLast( i, length ) && not( isConsumer( theInstance ))) {
System.err.println( "Invalid configuration: " + element + " most be a consumer ( either Ap...");
System.exit( 3 );
} else if ( isMiddleAndInvalid( i, length , instance ) ) {
System.err.println( "Invalid configuration: " + element + " most be a producer-consumer ( either Ap...");
System.exit( 4 );
}
}
private static Map<String,Class> implementationMap = new HashMap<String,Class>() static {
implementationMap.put( "AppleTree", AppleTree.class );
implementationMap.put( "ApplePieMaker ", ApplePieMaker .class );
implementationMap.put( "ApplePress", ApplePress.class );
implementationMap.put( "AppleSave", AppleSave.class );
implementationMap.put( "AppleLoad", AppleLoad.class );
implementationMap.put( "ApplePieMonitor", ApplePieMonitor.class );
};
// Utility methods to read better ( hopefully ) the statements
// If you could read the validations above you may ignore these functions.
private boolean not( boolean value ) {
return !value;
}
private boolean isFirst( int i ) {
return i == 0;
}
private boolean isLast( int i, int l ) {
return i == l -1 ;
}
private boolean isProducer( Object o ) {
return o instanceof Producer;
}
private boolean isConsumer( Object o ) {
return o instanceof Consumer;
}
private boolean isMiddleAndInvalid( int index, int length, Object instance ) {
return not( isFirst( index ) ) && not( isLast( index, length ) ) && not( isProducer( instance ) && isConsumer( instance ));
}
}
I believe what you are trying to do can be done within the Spring framework. It uses dependency injection to say "In order to create X I need Y, so find something that produces Y and see what you need in order to create it".
I may be wrong, but I suggest you have a look.
You would need some sort of Registry where producers could register (Hi, I'm an apple tree and I produce apples) and then the consumers could look up whom ever produces apples. This could also be done in reverse where the consumers register interest and the producers look up. I did something similar using JMX where an Object could query the JMX Server for an Object that produced a certain type of Message and then register with that Object (Publish/Subscribe). I am now porting that app to use OSGi which has a similar capability
Try the Java Beanshell.
BeanShell is a small, free, embeddable Java source interpreter with object scripting language features, written in Java. BeanShell dynamically executes standard Java syntax and extends it with common scripting conveniences such as loose types, commands, and method closures like those in Perl and JavaScript.

Categories