14 Replies - 1368 Views - Last Post: 08 September 2010 - 03:23 PM Rate Topic: -----

#1 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

how to assign created commands (objects) to a future event (object cre

Posted 05 September 2010 - 02:35 PM

Hi. this is my first post here. i hope ill stay here for a while.
I have a small project to make, a GUI interface with our planetary system.
http://www.gasuinfo....stem/index.html
all is well except that i can't make a spaceship with predefined commands.
so here is my task: i have 3 commands/buttons in my GUI - change speed factor (number by which is current speed multiplied), change direction, interval (ticks) between commands executing. So in my GUI i enter speed factor number, then interval number (after how many intervals next command is executed) then for example direction which is executed after n intervals which i entered and after that i click launch controlled ship and these commands should apply to this concrete ship which i launched

i have remade this problem with a smaller program, here it is
import java.util.*;

class Main {

    Controller controller = new Controller();
    Ship ship;

    public Main() {

        this.controller.speedFactor(ship, 10); // this command should apply to my ship which will be created in future
// i get nullpointer exception here...
        this.controller.executeCommands(controller.createShip(5,7));
        System.out.println(ship);
    }

    public static void main(String[] args) {
        new Main();
    }
} // end of class MainClass

class Controller {

    CommandControl cc = new CommandControl();
    Ship ship;

    /**
     * creates a ship with it's starting speed
     *  @return new ship
     */
    public Ship createShip(double speed, double direction) {
        return new Ship(speed, direction);
    }

    /**
     * command-method which changes the speed of the ship
     *  @param factor by which is speed multiplied
     */
    public void speedFactor(Ship ship, double factor) {
        cc.addCommand(new ChangeSpeed(ship, factor));
    }

    public void direction(Ship ship, double angle) {
        cc.addCommand(new ChangeDirection(ship, angle));
    }

    /**
     * executes the added commands for the ship in order
     */
    public void executeCommands(Ship ship) {
        cc.execute();
    }
} // end of class Controller

class Ship {

    CommandControl cc;
    double speed;
    double direction;

    public Ship(double speed, double direction) {
        this.speed = speed;
        this.direction = direction;
        //cc = new CommandControl();
    }

    public String toString() {
        return "Ship speed: " + speed + ", direction: " + direction;
    }
} // end of class Ship

interface Command {

    public abstract void execute();
} // end of interface Command

class CommandControl implements Command {

    private LinkedList<Command> commands;

    public CommandControl() {
        commands = new LinkedList<Command>();
    }

    /**
     * loops and executes each added command
     */
    public void execute() {

        // using iterator to avoid concurrent modification exception
        Iterator<Command> iterator;
        iterator = commands.iterator();
        while (iterator.hasNext()) {
            runSingleCommand();
        }
    }

    public void addCommand(Command c) {
        commands.addLast(c);
    }

    /**
     * runs a single command from the list and removes it.
     */
    public void runSingleCommand() {
        commands.getFirst().execute();
        commands.removeFirst();
    }
} // end of class CommandControl

class ChangeSpeed implements Command {

    Ship ship;
    double factor;

    /**
     * creates a new command for the ship
     */
    public ChangeSpeed(Ship ship, double factor) {
        super();
        this.ship = ship;
        this.factor = factor;
    }

    /**
     * changes the speed of the ship by multiplying with factor
     */
    public void execute() {
        this.ship.speed = this.ship.speed * factor;
    }
} // end of class ChangeSpeed

class ChangeDirection implements Command {

    Ship ship;
    double angle;

    public ChangeDirection(Ship ship, double angle) {
        super();
        this.ship = ship;
        this.angle = angle;
    }

    public void execute() {
        this.ship.direction = this.ship.direction * angle;
    }
}


as you see i minized that to only 2 commands. I have made it with command pattern cause the additional task is that in future i could easily add new types of commands.
I have bunch of questions.
1. Is it right that i implement the logic for the ship speed and angle changing in command class's execute method? I did that cause maybe if i had other types of ships which also can change their speed and angle i didn't have to remake the logic. Or should i have super abstract class for all ship's and make there an implementation logic?
2. So i rephrase my problem again: I receive commands to be applied to a future event(launch of ship) and need to queue them until the ship is launched (new Ship object created). When the new Ship object is created, then the commands in the queue should immediately be applied to the ship.
I'm not even sure that i made correct methods cause atm i can't add a command before the ship is created, i get nullpointer exception. but in my GUI i need to enter the commands for my future ship and then these commands are applied to the ship which i launch (by clicking launch planned spaceship).
if any1 wants to look for the application real code, then here it is: http://code.google.c...etarySystem/src

thanks for reading, any help or solution would be appreciated

Is This A Good Question/Topic? 0
  • +

Replies To: how to assign created commands (objects) to a future event (object cre

#2 macosxnerd101   User is online

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12648
  • View blog
  • Posts: 45,822
  • Joined: 27-December 08

Re: how to assign created commands (objects) to a future event (object cre

Posted 05 September 2010 - 04:19 PM

Ship is null at this point when you pass it in main(). You have to create an instance of an Object before you can pass it.
this.controller.speedFactor(ship, 10);


Was This Post Helpful? 0
  • +
  • -

#3 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 04:02 AM

Hi. Yes it is so atm, but how could i make it that i pass the not yet created object to my speedFactor or direction method? and after that my object is executed with the already passed in commands ?
Was This Post Helpful? 0
  • +
  • -

#4 Nasm   User is offline

  • New D.I.C Head

Reputation: 27
  • View blog
  • Posts: 47
  • Joined: 10-June 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 04:38 AM

It feels like you designed your program wrong. If you explain in more detail what your trying to accomplish I be more than happy to help.

To answer you question you can pass in a non-instantiated class as argument (actually a Class object) but really your problem has more to do with bad design/architecture.

This post has been edited by Nasm: 06 September 2010 - 04:38 AM

Was This Post Helpful? 0
  • +
  • -

#5 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 07:07 AM

View PostNasm, on 06 September 2010 - 03:38 AM, said:

It feels like you designed your program wrong. If you explain in more detail what your trying to accomplish I be more than happy to help.

To answer you question you can pass in a non-instantiated class as argument (actually a Class object) but really your problem has more to do with bad design/architecture.

Here is where i'm stuck and can't code any further, here i state what i want to do:
I receive commands to be applied to a future event(launch of ship) and need to queue them until the ship is launched (new Ship object created). When the new Ship object is created, then the commands in the queue should immediately be applied to the ship.
these commands are speed multiplying by factor and direction multiplying by factor. in my original GUI i want these commands to be chosen for my not-yet created spaceship and after i have added enough commands i launch the spaceship and the commands are executed to that spaceship. i didn't copy my whole project code cause noone would read that anyways and i made a simple small program which shows the problem/place where i'm stuck.

I'm sure that i have bad design for my program. I just hope somebody would lead me to the right way how to pass arguments to a non-instantiated class yet as you said.

maybe there's a topic for that kind of problem and you could say what for should i google?
Was This Post Helpful? 0
  • +
  • -

#6 Nasm   User is offline

  • New D.I.C Head

Reputation: 27
  • View blog
  • Posts: 47
  • Joined: 10-June 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 07:37 AM

I'm sorry, I still don't understand exactly what your trying to do. I think you need to explain the entire picture since it still doesn't make any sense to me.

Is ship the only kind of object being launched or is there other objects as well and should more than one ship exist at the same time?
Why do you send the ship as a parameter to the constructor in the command objects instead of the execute method? (from only seeing your example this would be a solution)
What is the reason why you want to avoid instancing ship objects?

If you simply launching one ship there is no sense in not instancing it or using events to apply the changes so I assume there is more to the program than your explaining (or you like over-designing).
Was This Post Helpful? 0
  • +
  • -

#7 macosxnerd101   User is online

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12648
  • View blog
  • Posts: 45,822
  • Joined: 27-December 08

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 08:12 AM

View Postskyzer, on 06 September 2010 - 07:02 AM, said:

Hi. Yes it is so atm, but how could i make it that i pass the not yet created object to my speedFactor or direction method? and after that my object is executed with the already passed in commands ?

You can't pass a nonexistent Object to be used. Once you create the Ship, then you can pass it to be launched. If you just want to Queue the Ship's commands, you can have it encapsulate a Queue<Command>, and pass them to it. Then, on launch, have it execute those Commands.
Was This Post Helpful? 0
  • +
  • -

#8 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 11:46 AM

View PostNasm, on 06 September 2010 - 06:37 AM, said:

I'm sorry, I still don't understand exactly what your trying to do. I think you need to explain the entire picture since it still doesn't make any sense to me.

Is ship the only kind of object being launched or is there other objects as well and should more than one ship exist at the same time?
Why do you send the ship as a parameter to the constructor in the command objects instead of the execute method? (from only seeing your example this would be a solution)
What is the reason why you want to avoid instancing ship objects?

If you simply launching one ship there is no sense in not instancing it or using events to apply the changes so I assume there is more to the program than your explaining (or you like over-designing).

lets say so i'd like in my main class first method to be add command change speed(factor = 10), second method create ship with speed of 5 and third print out that ship's speed which should be 50 (initial 5 * factor 10), not 5, because the change speed command is executed for my ship. if i'll get how to do that then i think i can manage myself everything else here. in my real GUI application i have 3rd command which is how much time to wait before executing the next command which i queued.
only 1 ship exists. that means i queue up my commands and then create ship and these commands are applied to that ship and emptied one by one.
why do i send the ship as a parameter to the constructor in the command objects? well i thought that i have to point somehow that these commands need to be applied for the ship. i haven't seen any examples about command pattern where execute() method has any parameters, heh.
as i said this mini program is just a small cut about my problem from my GUI application about the planet system (you can see that in my first post, and also the whole code for GUI in googlecode link).
this posted mini program really doesn't make sense, why would i need to multiply my ships speed by a factor before the ship is created and then print out the speed*factor value after that. it's just to show my question.

This post has been edited by skyzer: 06 September 2010 - 11:49 AM

Was This Post Helpful? 0
  • +
  • -

#9 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 11:54 AM

View Postmacosxnerd101, on 06 September 2010 - 07:12 AM, said:

View Postskyzer, on 06 September 2010 - 07:02 AM, said:

Hi. Yes it is so atm, but how could i make it that i pass the not yet created object to my speedFactor or direction method? and after that my object is executed with the already passed in commands ?

You can't pass a nonexistent Object to be used. Once you create the Ship, then you can pass it to be launched. If you just want to Queue the Ship's commands, you can have it encapsulate a Queue<Command>, and pass them to it. Then, on launch, have it execute those Commands.

yes i know it easy to say in words. but how could i make that in code. you mean my ship class should have new Queue<Command>() ? how would i make it in the launch that is would be binded to my ship?
Was This Post Helpful? 0
  • +
  • -

#10 Nasm   User is offline

  • New D.I.C Head

Reputation: 27
  • View blog
  • Posts: 47
  • Joined: 10-June 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 12:44 PM

Well I thought that the simplest solution is the best. Design patterns is there to help you, not to make it harder on you. When you have factory classes and thread pools for a hello world program something is wrong after all:)

Perhaps something as simple as this would work? Your only (reasonable) choices (that I can think of) is either to create the ship before you create the commands or pass it as an argument to the execute method.
Controller{
Queue<Command> commands;
execute(Ship ship){
while(commands.hasNext()){
Command c = commands.next();
c.execute(ship);
}
}
push_back(Command c){
commands.push_back(c);
}
}



For your timer approach an event queue could be useful (there is a lot of examples available if you do a search).
Was This Post Helpful? 1
  • +
  • -

#11 macosxnerd101   User is online

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12648
  • View blog
  • Posts: 45,822
  • Joined: 27-December 08

Re: how to assign created commands (objects) to a future event (object cre

Posted 06 September 2010 - 05:27 PM

Definitely agree with Nasm on the Factory pattern. :^:

Something I would suggest is an inner-class model, with the outer class being the Factory, and the inner class being the template. This way, you can organize multiple Ships to be created, like a standard Factory in real life, and each ShipTemplate also models the Factory pattern, creating a Ship once it is told to. I have a little code below to illustrate the design process, but hopefully it will help you to get started.
class Factory{

   private List<ShipTemplate> templates;

   class ShipTemplate{
        private Queue<Command> commands;
        
        public Ship createShip(){
            //code    
        }
 
   }

}


Was This Post Helpful? 0
  • +
  • -

#12 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 07 September 2010 - 07:19 AM

Hi again, i have tried to do again with your hints. But that skeleton code is just not enough for me to complete my task. Anyway i think that i'm very close to get my problem solved
package planetarysystem_mini;

import java.util.*;

class Main {

    Controller controller = new Controller();
    Ship ship;

    /**
     * imitated button which is on my GUI
     */
    public void speedButton(double factor) {
        controller.direction(factor);
    }

    public void directionButton(double direction) {
        controller.speedFactor(direction);
    }

    public Main() {

        directionButton(10); // this is like i'm pressing the button where i entered number 10 in the box
        ship = this.controller.createShip(5, 7); // ship created and must run the command it has (directionButton(10))
        System.out.println(ship); // should print out ship speed 50, but prints 5...
    }

    public static void main(String[] args) {
        new Main();
    }
} // end of class MainClass

class Controller {

    CommandControl cc = new CommandControl();
    Ship ship;

    /**
     * creates a ship with it's starting speed
     *  @return new ship
     */
    public Ship createShip(double speed, double direction) {
        return new Ship(speed, direction);
    }

    /**
     * command-method which changes the speed of the ship
     *  @param factor by which is speed multiplied
     */
    public void speedFactor(double factor) {
        cc.addCommand(new ChangeSpeed(ship, factor)); // create a new command
    }

    public void direction(double angle) {
        cc.addCommand(new ChangeDirection(ship, angle));
    }
} // end of class Controller

class Ship {

    CommandControl cc;
    double speed;
    double direction;

    public Ship(double speed, double direction) {
        this.speed = speed;
        this.direction = direction;
        //new CommandControl();
        getCommands().execute();
    }

    public String toString() {
        return "Ship speed: " + speed + ", direction: " + direction;
    }

    CommandControl getCommands() {
        return new CommandControl();
    }
} // end of class Ship

interface Command {

    public abstract void execute();
} // end of interface Command

class CommandControl implements Command {

    private LinkedList<Command> commands;

    public CommandControl() {
        commands = new LinkedList<Command>();
    }

    /**
     * loops and executes each added command
     */
    public void execute() {

        // using iterator to avoid concurrent modification exception
        Iterator<Command> iterator;
        iterator = commands.iterator();
        while (iterator.hasNext()) {
            runSingleCommand();
        }
    }

    public void addCommand(Command c) {
        commands.addLast(c);
    }

    /**
     * runs a single command from the list and removes it.
     */
    public void runSingleCommand() {
        commands.getFirst().execute();
        commands.removeFirst();
    }
} // end of class CommandControl

class ChangeSpeed implements Command {

    Ship ship;
    double factor;

    /**
     * creates a new command for the ship
     */
    public ChangeSpeed(Ship ship, double factor) {
        super();
        this.ship = ship;
        this.factor = factor;
    }

    /**
     * changes the speed of the ship by multiplying with factor
     */
    public void execute() {
        this.ship.speed = this.ship.speed * factor;
    }
} // end of class ChangeSpeed

class ChangeDirection implements Command {

    Ship ship;
    double angle;

    public ChangeDirection(Ship ship, double angle) {
        super();
        this.ship = ship;
        this.angle = angle;
    }

    public void execute() {
        this.ship.direction = this.ship.direction * angle;
    }
}


Here i have my commandcontrol in ship's constructor called out which commands should be executed to my concrete ship because in commands constructor as a parameter i have ship: ChangeDirection(Ship ship, double angle).
Everything runs okay, but the ship's speed isn't changed from its initial one.
But i have another problem now. On line 035 i create new CommandControl(). If i wouldn't create new CommandControl object, then i would get nullpointer exception on line 55 which is cc.addCommand(new ChangeDirection(ship, angle));. Debug shows that both cc and ship are null.

In Ship class i have encapsulated my CommandControl, and again if i don't return there new CommandControl object (line 77), then i'd get nullpointer exception on line 69 getCommands().execute();.

Atm my working program makes 2 different command controls, 1 in controller class and other in ship class.
other way in my controller class my direction method is following
public void direction(double angle) {
        ship.getCommands().addCommand(new ChangeDirection(ship, angle));
    }

but still i get nullpointer exception
Uhh i hope some day this problem will be solved. Any help please?
Was This Post Helpful? 0
  • +
  • -

#13 Nasm   User is offline

  • New D.I.C Head

Reputation: 27
  • View blog
  • Posts: 47
  • Joined: 10-June 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 07 September 2010 - 10:03 AM

Of course you get a nullpointerexception, you have the same exact problem as before. The ship isn't created when you push back the command. And then your never executing the commands on the ship when you create it. Please listen to our recommendations and have the ship as an argument to the execute method OR if you having commands your executing that change other aspect of the ship it could be easier if you create the ship in advance (but you don't have to draw or move it). Really it will practically solve all your problems in one easy step!
Was This Post Helpful? 0
  • +
  • -

#14 skyzer   User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 25
  • Joined: 05-September 10

Re: how to assign created commands (objects) to a future event (object cre

Posted 08 September 2010 - 10:50 AM

I have read here http://www.cs.toront...als/references/ about object creation, first example.
Lets say in my controller class if i just declare CommandControl cc; and in the same class cc.addCommand(new ChangeDirection(ship, angle)); then it will give me nullpointer exception, cause i haven't created new CommandControl(); object.
Same is in the ChangeDirection or ChangeSpeed execute method. I can't change ship's speed, because i can't assign to ship's speed directly the value, if the ship object wasn't created, but just declared Ship ship;.
Maybe it's better then in my ship class create another method
public void direction(double direction) {
        this.direction = this.direction * direction;
    }


and in ChangeDirection class the execute method is following:
public void execute() {
        this.ship.direction(angle);
    }

Was This Post Helpful? 0
  • +
  • -

#15 macosxnerd101   User is online

  • Games, Graphs, and Auctions
  • member icon




Reputation: 12648
  • View blog
  • Posts: 45,822
  • Joined: 27-December 08

Re: how to assign created commands (objects) to a future event (object cre

Posted 08 September 2010 - 03:23 PM

You are still missing the idea, which is to queue the Commands in a Template object, and have it create the Ship when the method is invoked. So keep passing commands to the Template object, then invoke createShip(), which creates the Ship, feeds the Commands to it, and returns it.

Also, there is a difference between declaring and instantiating an Object. Declaring your Object variable declares a null pointer, or an empty beer bottle if you want to use a metaphor. When you instantiate your new Object, you are creating the Object in memory and having the pointer point to it. Or metaphorically, filling the beer bottle with beer. At the root, this is where the majority of your problems lie.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1