OK, so in the spirit of Code-Golf, I\'m trying out something new here: Code-Bowling.
In golf, you try to get the lowest score (smallest application, mos
Java+Spring: All interfaces are injectable for unit testing!
package stackoverflow.codebowling;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ByteArrayResource;
import java.io.*;
import java.util.Random;
import java.util.logging.Logger;
public class Main {
/*
TODO: Add javadoc
*/
static public final Logger logger = Logger.getLogger(Main.class.getName());
public static void main(String[] args) throws IOException {
ByteArrayResource byteArrayResource =
new ByteArrayResource(spring_config_xml.getBytes());
XmlBeanFactory beanFactory = new XmlBeanFactory(byteArrayResource);
MessageWriter messageWriter = beanFactory.getBean("MessageWriterBean", MessageWriter.class);
try {
Writer writer = new PrintWriter(System.out);
messageWriter.writeMessage(writer);
writer.flush();
} catch(IOException ex) {
logger.severe(ex.getMessage());
throw ex;
}
}
/*
Using a visitor pattern to avoid casting or case statements.
If you see a case statement your are probably not doing real OOP
*/
static abstract public class TimeOfDay {
public abstract void visit(TimeOfDayVisitor visitor);
static final class Morning extends TimeOfDay {
@Override
public void visit(TimeOfDayVisitor visitor) {
visitor.morning(this);
}
}
static final class Afternoon extends TimeOfDay {
@Override
public void visit(TimeOfDayVisitor visitor) {
visitor.afternoon(this);
}
}
static final class Evening extends TimeOfDay {
@Override
public void visit(TimeOfDayVisitor visitor) {
visitor.evening(this);
}
}
static final class Night extends TimeOfDay {
@Override
public void visit(TimeOfDayVisitor visitor) {
visitor.night(this);
}
}
static public final TimeOfDay[] ALL = {
new Morning(),
new Afternoon(),
new Evening(),
new Night()
};
static public interface TimeOfDayVisitor {
public void morning(TimeOfDay timeOfDay);
public void afternoon(TimeOfDay timeOfDay);
public void evening(TimeOfDay timeOfDay);
public void night(TimeOfDay timeOfDay);
}
}
static public interface MessageWriter {
void writeMessage(Writer writer) throws IOException;
}
static public class MessageWriterImpl implements MessageWriter {
private TimeOfDayChooser timeOfDayChooser;
private TimeOfDayGreetingsFormatter timeOfDayGreetingsFormatter;
public void writeMessage(Writer writer) throws IOException {
TimeOfDay timeOfDay = timeOfDayChooser.choose();
writer.write(timeOfDayGreetingsFormatter.format(timeOfDay));
}
public void setTimeOfDayChooser(TimeOfDayChooser timeOfDayChooser) {
this.timeOfDayChooser = timeOfDayChooser;
}
public void setTimeOfDayGreetingsFormatter(TimeOfDayGreetingsFormatter timeOfDayGreetingsFormatter) {
this.timeOfDayGreetingsFormatter = timeOfDayGreetingsFormatter;
}
}
static public interface TimeOfDayGreetingsFormatter {
String format(TimeOfDay timeOfDay);
}
static public class TimeOfDayGreetingsFormatterImpl implements TimeOfDayGreetingsFormatter {
public String format(TimeOfDay timeOfDay) {
final StringBuilder builder = new StringBuilder();
builder.append("Good ");
timeOfDay.visit(new TimeOfDay.TimeOfDayVisitor() {
public void morning(TimeOfDay timeOfDay) {
builder.append("Morning");
}
public void afternoon(TimeOfDay timeOfDay) {
builder.append("Afternoon");
}
public void evening(TimeOfDay timeOfDay) {
builder.append("Evening");
}
public void night(TimeOfDay timeOfDay) {
builder.append("Night");
}
});
return builder.toString();
}
}
static public interface TimeOfDayChooser {
TimeOfDay choose();
}
static public class RandomTimeOfDayChooserImpl implements TimeOfDayChooser {
// *** injected by Spring
private RandomService randomService;
public synchronized TimeOfDay choose() {
int range = TimeOfDay.ALL.length;
int index = randomService.rand(range);
return TimeOfDay.ALL[index];
}
public void setRandomService(RandomService randomService) {
this.randomService = randomService;
}
}
static public class ChaoticTimeOfDayChooserImpl implements TimeOfDayChooser {
// *** injected by Spring
private RandomService randomService;
// *** this is initialized in the setter for randomService
private int currentIndex;
public synchronized TimeOfDay choose() {
int range = TimeOfDay.ALL.length;
this.currentIndex = this.currentIndex + 1 + randomService.rand(range - 1);
return TimeOfDay.ALL[this.currentIndex];
}
public void setRandomService(RandomService randomService) {
this.randomService = randomService;
int range = TimeOfDay.ALL.length;
this.currentIndex = randomService.rand(range);
}
}
static public interface RandomService {
int rand(int range);
}
static public class RandomServiceImpl implements RandomService {
// *** initialized by Spring
private long seed;
// *** initialized by setSeed
private Random random;
public int rand(int range) {
return (int)(random.nextInt(range));
}
/*
A seed of < 0 indicates a random seed. For testing, set a positive long value
which will guarantee reproducible results.
*/
public void setSeed(long seed) {
this.seed = seed;
if (seed >= 0) {
this.random = new Random(seed);
} else {
this.random = new Random();
}
}
}
static public final String spring_config_xml =
"\n" +
"\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n";
}