Mark F said:
I have a problem where I need one of several types returned depending on
a user selection. I was planning on using a factory pattern as these
types can all be related by a base class. The only problem is my
concrete classes may not have all the same properties. Can I still use
a factory pattern or should I use something else?
Example:
Abstract Class Document:
name
title
subject
Concrete Class Report extends Document:
reportno
keywords
Concrete class Drawing extends Document:
drawingno
That really depends on how the client application that
receives the newly created instance will use it. Seems
like you already think that polymorphic instances are
the way to go.
Well then, you'll likely want some interfaces like:
===============================================
public interface DocumentFactory
{
public abstract Document createDocument();
public abstract String getName();
public abstract String getTitle();
public abstract String getSubject();
}
public interface ReportFactory
extends DocumentFactory
{
public abstract Report createReport();
public abstract int getReportNumber();
public abstract String[] getKeywords();
}
public interface DrawingFactory
extends DocumentFactory
{
public abstract Drawing createDrawing();
public abstract int getDrawingNumber();
}
===============================================
The implementations look something like this:
===============================================
public abstract class DocumentFactoryAbstract
implements DocumentFactory
{
protected String name = "";
protected String title = "";
protected String subject = "";
public String getName()
{
return name;
}
public String getTitle()
{
return title;
}
public String getSubject()
{
return subject;
}
}
public abstract class ReportFactoryAbstract
extends DocumentFactoryAbstract
implements ReportFactory
{
protected int reportNumber;
protected String[] keywords = new String[] {};
public Document createDocument()
{
return createReport();
}
public int getReportNumber()
{
return reportNumber;
}
public String[] getKeywords()
{
return keywords;
}
}
public class ReportFactoryDefault
extends ReportFactoryAbstract
{
public Report createReport()
{
return /* whatever to create a Report */;
}
}
public abstract class DrawingFactoryAbstract
extends DocumentFactoryAbstract
implements DrawingFactory
{
protected int drawingNumber;
public Document createDocument()
{
return createDrawing();
}
public int getDrawingNumber()
{
return drawingNumber;
}
}
public class DrawingFactoryDefault
extends DrawingFactoryAbstract
{
public Drawing createDrawing()
{
return /* whatever to create a Drawing */;
}
}
===============================================
btw: I am too lazy to write the setter methods,
so I only included the getter methods.
Create your concrete factory classes that extend
either ReportFactoryAbstract or DrawingFactoryAbstract,
as appropriate. Instantiate the factories once and stuff
them into an array of type DocumentFactory[].
When the user selects an action to create something,
use the index of the selected action to select an object
from the DocumentFactory[]. Then call createDocument() on
that object to get an instance that is appropriate for the
selected action.
If you want to deal directly with the sub-type by using
downcasting, you can avoid using instanceof by using my
"Inheritance Descending" design pattern. If you don't
know that pattern, I can post an example later. It gives
the equivalent of an instanceof and downcast without
explicitly coding the instanceof or the downcast, so you
can work the actual sub-type.
--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!