//
Abstract Factory classes are often implemented with Factory Methods, but they
//
can also be implemented using Prototype. [GOF, p95]   Abstract Factory might
// store a set of Prototypes from
which to clone and return product objects.
// [GOF, p126]  Factory Method: creation through
inheritance. Protoype: creation
// through delegation.  Virtual constructor: defer choice of object
to create
// until run-time.
public class FactoryFmProto
{
static class Expression {
  
protected String str;
  
public Expression( String s ) { str = s; }
   public Expression cloan()     { return null; }
   public String     toString()  { return
str; }
}
static abstract class Factory {
   protected Expression prototype =
null;
   public Expression
makePhrase() { return prototype.cloan(); }
   public abstract Expression makeCompromise();
   public abstract Expression
makeGrade();
}
static class PCFactory extends Factory {
   public PCFactory() { prototype = new
PCPhrase(); }
   public Expression
makeCompromise() {
      return new
Expression( "\"do it your way, any way, or no way\"" );
}
   public Expression makeGrade()
{
      return new Expression(
"\"you pass, self-esteem intact\"" ); }
}
static
class NotPCFactory extends Factory {
  
public NotPCFactory() { prototype = new NotPCPhrase(); }
   public Expression makeCompromise() {
      return new Expression( "\"my
way, or the highway\"" ); }
  
public Expression makeGrade() {
      return new Expression( "\"take test, deal with the
results\"" ); }
}
public static void main( String[]
args ) {
   Factory factory;
   if (args.length > 0) factory = new
PCFactory();
   else                 factory = new
NotPCFactory();
   for (int i=0; i
< 3; i++) System.out.print( factory.makePhrase() + "  " );
   System.out.println();
  
System.out.println( factory.makeCompromise() );
   System.out.println( factory.makeGrade()
);
}
// D:\Java\patterns> java FactoryFmProto
//
"short"  "lie"  "old"
// "my way, or the
highway"
// "take test, deal with the results"
//
//
D:\Java\patterns> java FactoryFmProto 1
// "vertically
challenged"  "factually
inaccurate"  "chronologically
gifted"
// "do it your way, any way, or no way"
//
"you pass, self-esteem intact"
static class PCPhrase
extends Expression {
   static
String[] list = { "\"animal companion\"",
"\"vertically challenged\"",
                      "\"factually
inaccurate\"", "\"chronologically gifted\""
};
   private static int next =
0;
   public PCPhrase()         { super( list[next] );  next = (next+1) % list.length; }
   public Expression cloan() { return new
PCPhrase(); }
}
static class NotPCPhrase extends Expression
{
   private static String[] list =
{ "\"pet\"", "\"short\"",
"\"lie\"", "\"old\"" };
   private static int next = 0;
   public NotPCPhrase()      { super( list[next] );  next = (next+1) % list.length; }
   public Expression cloan() { return new
NotPCPhrase(); }
}}