Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

best way to decouple gui from logic

Status
Not open for further replies.

justride

Programmer
Jan 9, 2004
251
US
I am making a little simulator for some minor testing, just a little test thing for me that implements swing to run this little GUI. Right now I have my GUI and business logic tied together. I know that is not ideal so I am wondering how to efficiently decouple them.



I was doing this…
1. Main.java
2. SimulatorGUI.java
3. SimulatorLogic.java

I was using action events in the SimulatorGUI.java to invoke methods on my SimulatorLogic reference. However when certain things occur in my SimulatorLogic, lets say socket connection closed, I want to update the GUI status bar. What I did was make the SimulatorLogic extend the Simulator GUI and I would just call an inheritated update method() I know this sounds silly but thats all i thouht of at 12AM.

I guess what I am asking is, is there an efficient way, easy way for me to decouple these two where the SimulatorLogic can notify the GUI when needed.

Right now I have

Main.java
SimulatorGUI.java and an inner SimulatorLogic.java This way works but it seems like a poor way of coding this.
 
Use events. You write an interface class which extends java.util.EventListener and give it methods which represent the notifications you want to make from your application logic to your gui layer. The parameters to these interface methods can carry any extra information about the nature of the 'event'.

Code:
public interface MyListener extends EventListener {
  public void somethingHappend();
}

Then you'd have methods in your application logic class which allows implementations of these listeners to be added to it.

Code:
public class MyLogic {
  private ArrayList listeners = new ArrayList();

  public void addMyListener(MyListener l){
    synchronized ( listeners ){
      if ( !listeners.contains(l) ){
        listeners.add(l);
      }
    }
  }

  public void removeMyListener(MyListener l){
    synchronized ( listeners ){
      listeners.remove(l);
    }
  }

  private void fireSomethingHappend(){
    ArrayList cloneList = null;
    synchronized (listeners){
      cloneList = (ArrayList)listeners.clone();
    }

    Iterator itListeners = cloneList.iterator();
    while ( itListeners.hasNext() ){
      MyListener l = (MyListener)itListeners.next();
      l.somethingHappened();
    }
  }

  private void someLogicMethod(){

    //...

    //I need to inform interested parties (gui?) that
    //somethingHappened.
    fireSomethingHappend();

    //...
  }
}

Entities in your gui layer which want to know when 'somethingHappened' would implement the MyListener interface and then register themselves with your app logic like this:-
Code:
public class MyPanel extends JPanel implement MyListener {

   private MyLogic myLogic;

   public MyPanel(){

     //setup reference to logic class MyLogic
     // ...

     //register me with the logic class
     myLogic.addMyListener(this);
   }

   public void somethingHappened(){
     //this gets called when somethingHappened in myLogic
   }
}

You could also take a look at the java.util.Observer and java.util.Observable classes.

Tim
 
Sure, declare a public method and give the Logic a reference to the UI.

Btw, if you're trying to learn, maybe it's time to take a look at the model-view-controller pattern.

Cheers,
Dian
 
Events are a more decoupled way of informing gui layers from app logic layers. Indeed, the MVC pattern mandates that the model layer (which contains, or uses, application logic) not do direct method invocations on the view (gui) layer, but shoud use events instead.

Tim
 
Bah, I've done great implementatios of the MVC without using events. Why decoupling when you're trying to couple?

After all, firing an event is just calling a bunch of methods, they are not magic.

Cheers,
Dian
 
Well, it all depends upon why your trying to decouple your layers, I suppose. Having explicit 'notification' methods in your view means that the model needs to 'know' about the view. IMO it's not usually a good idea to have lower levels of an architecture coupled to higher ones.

firing an event is just calling a bunch of methods, they are not magic.

Yes, I know. It just a more decoupled way of doing it, which is what the OP seems to want to do.

Tim
 
So what's the difference between knowing the event you need to fire or the method you need to invoke? Events are nice someway to attend user input and for clear asynchronous processing, but I think that using them for another purposes, in a lot of cases, just add another level of indirection and complexity to a program.

Cheers,
Dian

 
...knowing the event you need to fire or the method you need to invoke

Knowing the event is different from hard-coding in the exact classes which need to know about the event.

...using them for another purposes, in a lot of cases, just add another level of indirection and complexity to a program.

Yes, I agree that more complexity is built in from the outset with events. It *might* save complexity later from the situation when you could have the model statically linked to lots of methods in the view layer.

The MVC pattern is designed to decouple the model from the view. The model can be reused with any views which know about the model and can handle the events. If you intend to use your logic without any gui, for instance, having a model which explicitly calls methods in a view makes this impossible without refactoring your code. Keeping coupling restricted to events means that ANY client code can make use of the model WITHOUT recourse to going into the model and hacking it.

Tim
 
Any view that you could think of must implement an interface in order to listen the events the model is firing. Well, let's just make the view implement another interface containing the methods the model will call and we have the same situation again.

I'm not saying events is not a good solution. Indeed Java has a robust event model that every Java programmer should know ant take advantage of it. But don't forget that asynchronous calls are complexity to your code, makes it harder to debug and splits the logic into several threads.

[quote:Tim]
If you intend to use your logic without any gui
[/quote]

Then I wouldn't bother implementing MVC :p

Cheers,
Dian

 
Then I wouldn't bother implementing MVC

Yeah, but what if your application logic was needed BOTH in a GUI situation and a 'headless' one driven from another application like a service?

Anyway, as usual, there are benefits and drawbacks on both sides of the argument.

Has the OP got any comments to make after all this discussion?

Tim
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top