99 Bottles of Beer/Java/Object Oriented

From Rosetta Code

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.

 
/*************************
* 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);
}
}