99 Bottles of Beer/Java/Object Oriented
Another solution for 99 Bottles of Beer, which in addition correctly handles the grammar. This solution is object-oriented. It is completely overkill for this problem.
<lang java> /*************************
* Interface for things. * *************************/
interface Thing {
String singular(); String plural();
}
/***************
* Containers. * ***************
Containers are things which can contain other things. The following class makes any thing into a container. The container class is actually a decorator which makes any thing into a container. Note that the contained thing is actually mutable, even if the container is not. Note that the container can only contain a single thing; if it shall contain several things, make it contain a collection instead. */
class Container implements Thing {
/** The format gives the name. %self% is replaced by the containing * object's name (in proper pluralization), %contained% is * replaced by the contained object's name. */ private final String format; private final Thing self; private final Thing containedThing;
public Container(String fmt, Thing what, Thing contained) { format = fmt; self = what; containedThing = contained; }
public String singular() { return format.replace("%self%", self.singular()) .replace("%contained%", containedThing.singular()); }
public String plural() { return format.replace("%self%", self.plural()) .replace("%contained%", containedThing.singular()); }
}
/*********************************
* A collection of equal things. * *********************************
In the context of this program, a collection of things is again considered a single thing. This is a concrete class. */
class EqualCollection implements Thing {
private int countOfThings; private final Thing typeOfThing;
public EqualCollection(int count, Thing what) { countOfThings = count; typeOfThing = what; }
/** get singular. The singular of the collection is just the number * followed by the thing, proper pluralized. The fact that it's * grammatically still a plural form doesn't matter for the problem * at hand. */ public String singular() { StringBuilder sb = new StringBuilder(); sb.append(countOfThings + " "); if (countOfThings == 1) sb.append(typeOfThing.singular()); else sb.append(typeOfThing.plural()); return sb.toString(); }
/** get plural. For collections, the plural is just "times " followed * by the singular. That is 3 collections of 4 bottles each give 3 * times 4 bottles. * This has to be implemented, even if it isn't used, * because the it is specified by the interface, and this * class is not abstract. */ public String plural() { return "times " + singular(); }
/** tell if there are still things to take away. There are things to * take away if there are more than 0 things. */ public boolean thereIsSomeLeft() { return countOfThings > 0; }
/** this takes one thing away from the collection. Taking a thing * away from an empty collection is undefined behaviour (i.e. not * explicitly checked). */ public void takeOneAway() { --countOfThings; }
}
/************
* The beer * ************/
class Beer implements Thing {
public String singular() { return "beer"; } public String plural() { return "beers"; }
}
/**************
* The bottle * **************/
class Bottle implements Thing {
public String singular() { return "bottle"; } public String plural() { return "bottles"; }
}
/************
* The wall * ************/
class Wall implements Thing {
public String singular() { return "wall"; } public String plural() { return "walls"; }
}
/** this is the class for the song. */ public class Song {
private final Thing beverage = new Beer(); private final Thing drinkSource = new Bottle(); private final Thing bottleOfBeer = new Container("%self% of %contained%", drinkSource, beverage); private final EqualCollection collectionOfBottles; private final Thing bottleStorage = new Wall(); private final Thing wallOfBottles;
public Song(int bottleCount) { collectionOfBottles = new EqualCollection(bottleCount, bottleOfBeer); wallOfBottles = new Container("%contained% on the %self%", bottleStorage, collectionOfBottles); }
public void sing(java.io.PrintStream where) { while (collectionOfBottles.thereIsSomeLeft()) { where.println(wallOfBottles.singular() + "."); where.println(collectionOfBottles.singular() + "."); where.println("Take one down, pass it around."); collectionOfBottles.takeOneAway(); where.println(wallOfBottles.singular() + "."); where.println(); } }
public static void main(String[] args) { Song song = new Song(100); song.sing(System.out); }
} </lang>