0

suppose i have Class A and class B and an interface called Message

public interface Message{
   public void sendMessage();
}

public class A implements Message{
   @Override
    public void sendMessage(){
      //call the sendMessage() in class B.
    }
}

public class B implements Message{
    @Override
     public void sendMessage(){
       System.out.println("Hola Stack!");
      }

 }

without a direct reference to class B can i somehow invoke the sendMessage() method in class B from class A?

3alto
  • 189
  • 1
  • 9
  • First, you would need to define a variable in ClassA so you can reference the `ClassB` object. Instead of having the variable typed as `ClassB`, type ot as `Message`, then initialize it using an instance of `ClassB`, possibly via DI to ensure A does not know about B – Vince Nov 27 '15 at 20:32
  • 1
    This sort of problem can be solved using an [event bus](http://stackoverflow.com/questions/3987391/why-people-use-message-event-buses-in-their-code). That way the sender doesn't need to know (or care) who is receiving messages, but can still trigger action in the receiving class (e.g. B listens to A, when it sees a message, it calls its own `sendMessage()` method). – azurefrog Nov 27 '15 at 20:37

3 Answers3

2

Of course you can.

class ClassA {
    private Message message;

    public ClassA(Message message) {
        this.message = message:
    }

    public void sendMessage() {
        message.sendMessage();
    }
}

Simply pass an instance of B to A:

Message b = new ClassB();
Message a = new ClassA(b);
a.sendMessage();
Vince
  • 14,470
  • 7
  • 39
  • 84
0

You are kind of misusing interfaces here. Sure, you can use

    Message a = new B();
`   a.sendMessage();

That will do what you want, but is not desired practice and not what you want. If you want A and B to be interchangeable, you should make A super class and have B inherit from it like this, dropping the interface:

public class A {

    public void sendMessage(){
      //call the sendMessage() in class B.
    }
}

public class B extends A{
    @Override
     public void sendMessage(){
       System.out.println("Hola Stack!");
      }

 }

This way you can do this:

A a = new B();
a.sendMessage(); //  prints inside of B, but you tell the JVM to forget it is B, and think it is A

Just remember, if you want classes to be interchangeable, the child class must have all the functionality of A, and you cannot use functionality of B that is not defined in A (either as concrete or abstract method)

The Law
  • 344
  • 3
  • 20
0

You can use at least these two design patterns to solve your problem:

  • Observer
  • Mediator

Depending on your use case of your application one can be better than other, but both solve the issue of high coupling between objects. The difference between them is that the Observer pattern will introduce "Observer" and "Subject" objects whereas a Mediator will encapsulate the communication between objects. You could combine both patterns for your solution using two interfaces as the following example:

import java.util.*; 

public class TestAB {

    public static void main(String args[]) {

        Mediator messageBus = new Mediator();

        ClassA objA = new ClassA();

        ClassB objB = new ClassB();
        messageBus.register("ClassB", objB);

        objA.sendMessage(messageBus, "ClassB", "Hello class B!");
    }
}

class ClassA {

    public void sendMessage(Mediator bus, String dest, String text) {
        // send message to the sendMessage() in class B.
        bus.sendMessage(new Message() {
            public String getDestination() { return dest; }
            public String getText() { return text; }
        });
    }

}

class ClassB implements Observer {

    public void sendMessage(Message msg){
        System.out.println("sendMessage from ClassB received: "+ msg.getText());
    }
    public String getId(){
        return "B";
    }
    public void onMessage(Message msg) {
        // listen to message calls from the message bus (Mediator)
        sendMessage(msg);
    }
}

interface Message {
    public String getDestination();
    public String getText();
}

interface Observer {
    public String getId();
    public void onMessage(Message msg);
}

class Mediator {
    Map<String, Observer> observerList = new HashMap<String, Observer>();
    protected void register(String id, Observer obj) {
        observerList.put(id, obj);
    }
    protected void sendMessage(Message msg) {
        Observer obj = observerList.get(msg.getDestination());
        obj.onMessage(msg);
    }
}

All classes that want to receive messages need to implement the interface Observer, in this case B implements the Observer interface and calls its own "sendMessage" method when some message arrives. Finally we created a TestAB class with the mediator object (message bus) responsible to deliver the messages from A to B objects.

For the sake of simplicity I tried to avoid some refinements on the implementation, if you want to know more about these patterns you can get more information in the following link

https://sourcemaking.com/design_patterns/mediator

brunocrt
  • 720
  • 9
  • 11