0

Assume:
A simple modular java library has only two module:

package com.mycorp.lib.logger;
public class LogcatLogger implements Logger {

    @Override
    public void out(LogcatLogger.LogMessage message){
        Log.i("TAG", message.status);
    }

    ...
}

package com.mycorp.lib.webservice;
public class JsonWebservice implements Webservice {

    @Override
    public void onErrorFound(String status) {
        LogcatLogger.LogMessage message = new LogcatLogger.LogMessage();
        message.status = status;
        LogcatLogger.out(message);
    }

    ...
}

Question:
How to make com.mycorp.lib.webservice and com.mycorp.lib.logger independent like this? ( client application can invoke methods too ) Target Design

Notes:
I try Command Pattern before:
Result: api has many methods and many command class must create

Update1:
Added LogMessage as nested static class of LogcatLogger for more challenging situation

Update2:
Target Design image added.

Any help appreciated.

Behnam
  • 2,212
  • 2
  • 22
  • 32
  • Regards to your update2: is the `Logger` interface part of `com.mycorp.lib.logger`? If so, you will always depend on that package with `webservice`. – corsiKa Aug 03 '12 at 20:35
  • I decide to move `Logger` into `com.mycorp.lib.invoker`, so every consumer can access to the API – Behnam Aug 03 '12 at 20:41

1 Answers1

1

Use the Strategy Pattern. Basically, make LogcatLogger implement a custom interface, and reference that interface in the service.

package com.mycorp.lib.invoker;
public interface Logger {
    void out(Loggable message);
}

package com.mycorp.lib.invoker;
public interface Loggable {
    void setStatus(String status);
    String getStatus();
}

package com.mycorp.lib.invoker;
public class LoggableFactory {
    public static Loggable createDatabaseLogMessage() { return new DatabaseLogMessage(); }
    public static Loggable createWebserviceLogMessage() { return new WebserviceLogMessage(); }
}

package com.mycorp.lib.logger;
public class WebserviceLogMessage implements Logger {

    @Override public void out(Loggable message){
        Log.i("TAG", message.getStatus());
    }

    ...
}

package com.mycorp.lib.logger;
public class DatabaseLogMessage implements Logger {
    @Override public void out(Loggable message) {
        Log.i("JDBC",message.getStatus());
        otherFancyStuff(); // whatever ? :)
    }
}

package com.mycorp.lib.webservice;
public class JsonWebservice implements Webservice {
    Logger out;

    JsonWebservice(Logger out) { this.out = out; }

    @Override
    public void onErrorFound(String status) {
        Loggable message = LoggableFactory.createWebserviceLogMessage();
        message.setStatus(status);
        out.out(message);
    }

    ...
}
corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • thanks for answer. but **Logger** already defined **out** and is same as **LogMessageConsumer**, also where we specify what **LogMessageConsumer** implemented class must be used to invoke it's **out** method? If you mean after **LogMessageConsumer out = new LogcatLogger();** again we have dependency to **com.mycorp.lib.logger** – Behnam Aug 03 '12 at 19:34
  • If you have `LogMessageConsumer out = new LogcatLogger()` then yes you have it. If you instead have something else that does `myJsonWebservice.setLogMessageConsumer(new LogcatLogger())` then you don't. They're still independent. – corsiKa Aug 03 '12 at 19:58
  • Also, if `Logger` already defines `out` then simply replace all references to `LogMessageConsumer` with `Logger` in your service, and add your `setLogMessageConsumer(Logger logger)` method to the service, or add it to your constructor. In this way, `JsonWebservice` only ever depends on `Logger` and its package - never on `LogcatLogger` and its package. Note that if `Logger` is a member of the same package as `LogcatLogger` then you're screwed - it will have a dependency. – corsiKa Aug 03 '12 at 20:01
  • Very nice! and what about **LogcatLogger.LogMessage** that is unique per **Logger** like **LogcatLogger** or **DatabaseLogger**, please see Update1 – Behnam Aug 03 '12 at 20:04
  • Making `LogMessage` a child class of `LogcatLogger` will make you incur a dependency. You could get around this, however, by either making `class LogcatLogMessage extends LogMessage` or by making `LogMessage implements Loggable` where `Loggable` is an interface I made up with all your LogMessage behaviors. – corsiKa Aug 03 '12 at 20:33
  • Many Thanks, need more work on the solution to find out more. – Behnam Aug 03 '12 at 20:42
  • I have added a more complete solution. It uses a `Factory` class to create `Loggable` objects that you can send to your `Logger` objects. – corsiKa Aug 03 '12 at 20:51