简体   繁体   中英

Communication between several classes

Whenever I make a program I tend to divide different sections in different files, I think it looks more neat that way. To make the problem more concrete say I have this dummy code consisting of four classes,

public class dummy {
    public static void main(String[] args){
        Alpha a = new Alpha();
        Beta b = new Beta();
        Gamma g = new Gamma();

        int x,y,z,j,k,l,o,p,q;

        x = a.getGammaX();
        y = b.getGammaX();
        z = g.getX();

        a.setGammaX(1);

        j = a.getGammaX();
        k = b.getGammaX();
        l = g.getX();

        b.setGammaX(2);

        o = a.getGammaX();
        p = b.getGammaX();
        q = g.getX();
        }
    }

class Alpha{
    Gamma g = new Gamma();
    public int getGammaX(){
        return g.getX();
    }

    public void setGammaX(int x){
         g.setX(x);
    }
}

class Beta{
    Gamma g = new Gamma();
    public int getGammaX(){
        return g.getX();
    }

    public void setGammaX(int x){
        g.setX(x);
    }
}

class Gamma{
    int x = 10;

    public int getX(){
        return x;
    }
    public void setX(int y){
        x = y;
    }
}

The Alpha and Beta classes communicate with the Gamma. The purpose of the integers is to print out their values and compare them with each other after the setters have been called from the different classes. A general problem I have when I split the sections is that when one class change the values in Gamma, the other classes have obsolete values, the x,y,z variables will still have the old values of x in Gamma when a setter method has been called, unless I discover this before spending quite some time finding it.

I tend to circumvent this by passing around one reference of the Gamma class,

Gamma g = new Gamma();
Alpha a = new Alpha(g);
Beta b = new Beta(g);

like so, and spend several lines of code to update everything. Where the reference is being created from the "main" class, where "main" is not necessarily the class with the main method, but the class where the most action is.

The question I have is, is there a standard way of dealing with this kind of problem, where multiple classes communicate with one other class, changing values etc. and ending up with obsolete values?

My problems tend to be more subtle than what is shown but essentially this is what I tend to spend some time on trying to fix. I am sorry if the explanation is muddy, I had a hard time to make the problem this clear, if it is too incomprehensible, write in the comments where and I will try to clear it a bit more clearer.

The standard way of dealing with this is the so-called observer pattern .

You should make sure that there is only one instance of Gamma , as otherwise you have to make sure all instances are synchonized.

a and b ask g to be registered as observers. g notifies all its observers of a change of its state.

class Gamma extends Observable {
    int x = 10;

    public int getX(){
        return x;
    }
    public void setX(int y){
        x = y;
        notifyObservers (null);
    }
}

class Alpha implements Observer {
    // ...

    public Alpha (Gamma g) {
       g.addObserver (this);
    }

    public void update(Observable o, Object arg) {
       // this method gets called by g whenever g's state changes
       // do necessary updates here
       // ...
    }
 }

Use the MVC (model-view-control) pattern or one of its variants, and have classes that need to hold the same data share a model. For instance perhaps Gamma is your model, then have the other classes share the same Gamma instance .

eg,

public class Dummy {
   public static void main(String[] args) {
      Gamma g = new Gamma();

      Alpha a = new Alpha(g);
      Beta b = new Beta(g);

      // .........


   }
}

class Alpha {
   private Gamma g;

   public Alpha(Gamma g) {
      this.g = g;
   }

   public int getGammaX() {
      return g.getX();
   }

   public void setGammaX(int x) {
      g.setX(x);
   }
}

class Beta {
   // Gamma g = new Gamma();
   private Gamma g;

   public Beta(Gamma g) {
      this.g = g;
   }

   public int getGammaX() {
      return g.getX();
   }

   public void setGammaX(int x) {
      g.setX(x);
   }
}

class Gamma {
   int x = 10;

   public int getX() {
      return x;
   }

   public void setX(int y) {
      x = y;
   }
}

To have have classes notified of state changes on another class, then use, use an observer pattern as recommended by JohnB.


Note that one way to gain observer support is to use JavaBean's PropertyChangeSupport. For example:

class Gamma {
   public static final String X = "x";
   private PropertyChangeSupport support = new PropertyChangeSupport(this);

   private int x = 10;

   public int getX() {
      return x;
   }

   public void setX(int x) {
      int oldValue = x;
      int newValue = this.x;
      this.x = x;
      support.firePropertyChange(X, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      support.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      support.removePropertyChangeListener(listener);
   }
}

Note: probably the nicest and cleanest way to inject the A and B classes with a shared Gamma class is via dependency injection such as available from one of Spring's modules or from the Guice framework.

If you really wanted to do this... to use the Observer pattern as mentioned by JohnB.

But, I don't entirely agree with your reason. Splitting up code across classes is not a good reason to use observer pattern. There should be a better / more functional requirement than that. Of course I do not know the exact requirement so I can't generalize.

I would suggest a very different approach. Start with a base class that adds little bit of functionality and then keep extending layer by layer to add more functionality.

This will let you have beautifully crisp code which is readable and maintainable while also keeping your object model representative of the functionality.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM