Skip to content

Instantly share code, notes, and snippets.

@hakanai
Created January 13, 2010 01:31
Show Gist options
  • Save hakanai/275831 to your computer and use it in GitHub Desktop.
Save hakanai/275831 to your computer and use it in GitHub Desktop.
/**
* Interface for printers.
* <p>
* Printers are capable of printing a message, but the abstraction does not
* require a printer to print to any particular destination.
*/
public interface Printer {
/**
* Prints the message.
* <p>
* Implementers are generally expected to call
* {@link Message#accept(MessageVisitor)} and then feed each visited
* message part to some destination of their choosing.
*
* @param message the message to print.
*/
void print(Message message);
}
/**
* Implementation of a printer which writes to the standard output stream.
*/
public class SystemOutPrinter implements Printer {
@Override
public void print(Message message) {
message.accept(new MessageVisitorAdapter() {
@Override
public void visitMessageBody(String messageBody) {
System.out.println(messageBody);
}
});
}
}
/**
* Interface holding the configuration for the application.
*/
public interface ApplicationConfig {
/**
* Gets the message to display.
*
* @return the message to display.
*/
String getMessage();
}
/**
* Default implementation of the application configuration interface, simply
* feed the configuration into the constructor.
*/
public class DefaultApplicationConfig implements ApplicationConfig {
/**
* The message to display.
*/
private final String message;
/**
* Constructs the application configuration object.
*
* @param message the message to display.
*/
public DefaultApplicationConfig(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
/**
* Interface for message objects.
*/
public interface Message {
/**
* Accepts a visitor to each part of the message object. Can be used to
* get at the parts of the message to perform various optimisations on
* them.
*
* @param visitor the visitor.
*/
void accept(MessageVisitor visitor);
}
/**
* Interface to be implemented when you wish to visit a message.
*
* @see Message#visit(MessageVisitor)
*/
public interface MessageVisitor {
/**
* Called when visiting the message body.
*
* @param messageBody the message body.
*/
void visitMessageBody(String messageBody);
}
/**
* Do-nothing implementation of {@link MessageVisitor} for forwards
* compatibility.
*/
public abstract class MessageVisitorAdapter {
@Override
public void visitMessageBody(String messageBody) {
// Do nothing.
}
}
/**
* Default implementation of a message.
* <p>
* Stores the message as an ordinary Java field.
*/
public class DefaultMessage implements Message {
/**
* The message body.
*/
private final String messageBody;
/**
* Constructs the message.
*
* @param messageBody the message body.
*/
public DefaultMessage(ApplicationConfig config) {
messageBody = config.getMessage();
}
@Override
public void accept(MessageVisitor visitor) {
visitor.visitMessageBody(messageBody);
}
}
/**
* Interface to run the application itself.
*/
public interface Application {
/**
* Runs the application.
*/
void run();
}
/**
* Default implementation of the application itself.
*/
public class DefaultApplication implements Application {
/**
* The printer to use for displaying the message.
*/
private final Printer printer;
/**
* The message to display.
*/
private final Message message;
/**
* Constructs the application.
*
* @param printer the printer to use for displaying the message.
* @param message the message to display.
*/
public DefaultApplication(Printer printer, Message message) {
this.printer = printer;
this.message = message;
}
@Override
public void run() {
printer.print(message);
}
}
/**
* Main class.
*/
public class Main {
/**
* Main entry point.
*
* @param args command-line arguments (ignored.)
*/
public static void main(String[] args) {
MutablePicoContainer container = new DefaultPicoContainer();
container.addComponent(Printer.class, SystemOutPrinter.class);
container.addComponent(Message.class, DefaultMessage.class);
container.addComponent(Application.class, DefaultApplication.class);
container.addComponent(ApplicationConfig.class, new DefaultApplicationConfig("Hello, World!"));
container.start();
Application app = container.getComponent(Application.class);
app.run();
container.stop();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment