Interface or Abstract class - java

My Java is a bit rusty, and I am sure I am doing this wrong
I have a whole bunch of different fileformats that I need to export. So I though I would create a class for each format, and have them all implement a standard Interface.
Each document has a name, and default filename, but I am not sure how I should store that data correctly. Initially I thought it should be a static final string in the concrete class, but then how do I enforce it via the interface so that all concrete classes have to supply that info.
Hope this makes sense, this is what I have so far
public interface IExporter {
public void exportToFile(String filename) throws SQLException, IOException;
public String getDocumentName();
public String getDefaultFilename();
}
-
public class LaneDrawCsvExporter implements IExporter {
public void exportToFile(String filename) throws SQLException, IOException {
// code to export document here
}
public String getDocumentName() {
return "Lane Draw";
}
public String getDefaultFilename() {
return "Lane Draw.CSV";
}
}

Your approach looks reasonable. As for how to enforce having to supply doc name and default filename, I think what you've done works -- having methods in the interface that return the doc name and the default filename. All concrete classes implementing the interface will have to implement those methods to even be able to compile. Thus you've enforced the requirement that the concrete classes have to supply those names. I think trying to enforce that concrete classes have a particularly-named static final string is a red herring since you have those methods available.

Separate the information on the files from the Exporters. So you have a bunch of Exporters whose only tasks is to export the file, and some object that links to the file and the right exporter (and maybe some addition constructs to decide which Exporter to use).

I would create an abstract class called BaseIEExporter or something and then provide a couple (or more) instance variables and their getter and setter methods within (like name/filename). Or the common characteristics between all implementing classes.
When you create a new class extending the abstract class, just have the overloaded constructor provide whatever parameters you need supplied.
This way the process of creation of a certain class, would require you to provide the needed information i.e the constructor requires it.

If you need to force to set up the initial state of your class(filename etc) it would be better to use an Abstract class.
The below is just to give you an idea(you need to refactor it)
NOTE: As there is no default (or no-arg) constructor in the parent abstract class the constructor used in subclasses must be specified.
public abstract class Exporter {
string FileName
public Exporter ( string fileName ) {
FileName= fileName
}
public void exportToFile() ....
public String getDocumentName()....
public String getDefaultFilename()....
}
-
public class LaneDrawCsvExporter extends Exporter {
public LaneDrawCsvExporter ( string fileName ) {
super(fileName)
}
public void exportToFile() throws SQLException, IOException {
// code to export document here
}
public String getDocumentName() {
return "Lane Draw";
}
public String getDefaultFilename() {
return "Lane Draw.CSV";
}
}

Related

Factories in Java without a switch statement

I am trying to build a factory object, but having trouble working out a good way of doing it in Java.
The application I am writing is used for processing files in various formats, so there is a CodecInterface which applies to all classes which are used for reading and writing files. Let's assume it defines the following methods. Each of these files has a unique human-designated ID string which is used for id'ing the encoder\decoder.
String read();
void write(String data);
String getID();
The factory class would have a create method which is intended to create instances of these codec classes. I imagine the method signature would look something like this.
static CodecInterface CodecFactory.create(String filename, String codecid, String args);
The filename is the name of the file to read/write, and the codecid is the unique ID indicating what codec to use. The args parameter is a string of arguments passed to the decoder/encoder object being generated. The return of this should be an instance of the requested codec object.
All of the Factory examples I have seen typically have a switch statement inside of the create method which creates an object instance dependent on the ID. I want to avoid doing it this way as it doesn't seem like the 'right' way, and it also means that the list is more or less fixed unless you modify the create method. Ideally I would like to use something like a dictionary (indexed by the codec ID) which contains something which can be used to create an instance of the codec classes I want (I will call this mystery class ClassReference). Again to use some quasi-java code, here is what I was thinking as the body for the create method.
static Dictionary<String, ClassReference>;
static CodecInterface CodecFactory.create(String filename, String codecid, String args);
{
ClassReference classreference;
classreference = codeclibrary(codecid);
return classreference.instanceOf(args);
}
The dictionary of ID's is easy enough, but I can't work out what ClassReference should be. Class Reference should allow me to create an instance of the desired class, as in the example above.
From looking around online, the class method, and instanceOf seem to be heading in the right direction, but I haven't found anything which puts the two together. As an added complication, the constructors for the objects being created will have arguments.
Any tips on what I should be looking at would be greatly appreciated.
Thanks in advance.
SOLUTION
Thanks everyone for your advice. I've ended up taking bits and pieces from all of your suggestions and came up with the following which seems to work as I wanted.
Note that I have omitted much of the sanity\error checking code to show off the important bits.
import java.lang.reflect.Constructor;
import java.util.HashMap;
public class CodecFactory
{
private static HashMap<String, Class<? extends CodecInterface>> codecs;
static
{
codecs = new HashMap<String, Class<? extends CodecInterface>>();
//Register built-in codecs here
register("codecA", CodecA.class);
register("codecB", CodecB.class);
register("codecC", CodecC.class);
}
public static void register(String id, Class<? extends CodecInterface> codec)
{
Class<? extends CodecInterface> existing;
existing = codecs.get(id);
if(existing == null)
{
codecs.put(id, codec);
}
else
{
//Duplicate ID error handling
}
}
public static CodecInterface create(String codecid, String filename, String mode, String arguments)
{
Class<? extends CodecInterface> codecclass;
CodecInterface codec;
Constructor constructor;
codec = null;
codecclass = codecs.get(codecid);
if(codecclass != null)
{
try
{
constructor = codecclass.getDeclaredConstructor(String.class, String.class, String.class, String.class);
codec = (CodecInterface)(constructor.newInstance(codecid, filename, mode, arguments));
}
catch(Exception e)
{
//Error handling for constructor/instantiation
}
}
return codec;
}
}
Try something like that:
public class CodecFactory {
final private static Map<String, Class<? extends CodecInterface>> codecLibrary;
static {
codecLibrary = new HashMap<String, Class<? extends CodecInterface>>();
codecLibrary.put("codec1", Codec1.class);
//...
}
static CodecInterface create(String filename, String codecid, String args) throws InstantiationException, IllegalAccessException {
Class<? extends CodecInterface> clazz;
clazz = codecLibrary.get(codecid);
CodecInterface codec = clazz.newInstance();
codec.setArgs(args);
codec.setFilename(filename);
return codec;
}
}
There's a zillion options. For example, you might create a base factory class that also has static methods to manage registered factories (untested code typed here, sorry for errors):
public abstract class CodecFactory {
private final String name;
public CodecFactory (String name) {
this.name = name;
}
public final String getName () {
return name;
}
// Subclasses must implement this.
public abstract Codec newInstance (String filename, String args);
// --- Static factory stuff ---
private static final Map<String,CodecFactory> factories = new HashMap<String,CodecFactory>();
public static void registerFactory (CodecFactory f) {
factories.put(f.getName(), f);
}
public static Codec newInstance (String filename, String codec, String args) {
CodecFactory factory = factories.get(codec);
if (factory != null)
return factory.newInstance(filename, args);
else
throw new IllegalArgumentException("No such codec.");
}
}
Then:
public class QuantumCodecFactory extends CodecFactory {
public QuantumCodecFactory {
super("quantum");
}
#Override public Codec newInstance (String filename, String args) {
return new QuantumCodec(filename, args);
}
}
Of course this means at some point you must:
CodecFactory.registerFactory(new QuantumCodecFactory());
Then usage is:
Codec codec = CodecFactory.newInstance(filename, "quantum", args);
Another option is to use reflection and maintain a Map<String,Class<? extends CodecInterface>>, using Class.newInstance() to instantiate. This is convenient to implement because it works on top of Java's Class, which already supports a factory-style model for instantiating objects. The caveats are, like above the classes must be explicitly registered, and also (unlike above) you can't implicitly enforce constructor parameter types at compile-time (although you could at least abstract it behind some method instead of calling Class.newInstance() directly from client code).
For example:
public final class CodecFactory {
private static final Map<String,Class<? extends Codec>> classes = new HashMap<String,Class<? extends Codec>>();
public static void registerClass (String name, Class<? extends Codec> clz) {
classes.put(name, clz);
}
public static Codec newInstance (String filename, String codec, String args) {
Class<? extends Codec> clz = classes.get(codec);
if (clz != null)
return clz.getDeclaredConstructor(String.class, String.class).newInstance(filename, args);
else
throw new IllegalArgumentException("No such codec.");
}
}
Where every Codec is expected to have a constructor that takes (String filename, String args). Registration, then, is:
CodecFactory.registerClass("quantum", QuantumCodec.class);
Usage is the same as above:
Codec codec = CodecFactory.newInstance(filename, "quantum", args);
You could even leave out the map and just use Class.forName() -- this doesn't give you as much flexibility with codec names, but it essentially lets the class loader do all of the work for you and you don't need to explicitly register types ahead of time.
Edit: Re: Question in comments below. You could come up with a system that combined the two above examples to create a reusable, reflection based generic factory derived from CodecFactory, which still leaves you with the ability to create other more specialized factories, e.g.:
public class GenericCodecFactory extends CodecFactory {
private final String name;
private final Class<? extends Codec> clz;
public GenericCodecFactory (String name, String clzname) {
this.name = name;
this.clz = Class.forName(clzname);
}
public GenericCodecFactory (String name, Class<? extends Codec> clz) {
this.name = name;
this.clz = clz;
}
// parameter type checking provided via calls to this method, reflection
// is abstracted behind it.
#Override public Codec newInstance (String filename, String args) {
return clz.getDeclaredConstructor(String.class, String.class).newInstance(filename, args);
}
}
Then you could use that for whatever:
// you can use specialized factories
ClassFactory.registerFactory(new QuantumCodecFactory());
// you can use the generic factory that requires a class at compile-time
ClassFactory.registerFactory(new GenericCodecFactory("awesome", AwesomeCodec.class));
// you can use the generic factory that doesn't need to have class present at compile-time
ClassFactory.registerFactory(new GenericCodecFactory("ninja", "com.mystuff.codecs.NinjaCodec"));
As you can see, there's a ton of possibilities. Using Class.forName() in reflection-based factories is nice because the class doesn't need to be present at compile-time; so you can drop in codec classes on the class path and, say, specify a list of class names in a run-time configuration file (then you could have static ClassFactory.registerFactoriesListedInFile(String confgFilename) or something), or scan a "plugin" directory. You can even construct class names from simpler strings, if you're comfortable with that, e.g.:
public class GenericPackageCodecFactory extends GenericCodecFactory {
public GenericPackageCodecFactory (String name) {
super(name, "com.mystuff." + name + ".Codec");
}
}
You could even use something like that as a fallback in ClassFactory if the codec name is not found, to get around having to explicitly register types.
The reason reflection keeps popping up, by the way, is that it's very flexible and the Class interface is essentially an all-encompassing class factory, so it frequently parallels what specific factory architectures are trying to accomplish.
Another option is to use the second example I mentioned above (with the Map<String,Class>) but make a version of registerFactory that takes a String class name instead of a Class, similar to the generic implementation I just mentioned. That's probably the least amount of code required to avoid having to create instances of CodecFactorys.
I can't possibly give examples for every combination of things you can do here, so here is a partial list of the tools you have available, which you should use as you see fit. Remember: Factories are a concept; it's up to you to use the tools you have to implement that concept in a clean way that meets your requirements.
Reflection (Class<?> and Class.forName)
Static initializer blocks (sometimes a good place to register a factory; requires class to be loaded, but Class.forName can trigger this).
External configuration files
Plugin frameworks like http://jpf.sourceforge.net/ or https://code.google.com/p/jspf/ or https://code.google.com/p/jin-plugin/ (good comparison of OSGi, JPF, JSPF can be found here; I've never heard of jin-plugin prior to looking through the answers in the link).
Maps of registered factories and/or ability to use reflection to generate class names on the fly.
Don't forget concurrent maps and/or synchronization primitives for multi-threaded support if necessary.
Lots of other stuff.
Also: Don't go crazy implementing all of these possibilities if you don't have to; think about your requirements and decide on the minimum amount of work you need to do here to meet them. For example, if you need extensible plugins, JSPF alone might be enough to satisfy all of your requirements without you having to do any of this work (I haven't actually checked it out, so I'm not sure). If you don't need that kind of plugin "scanning" behavior, simple implementations like the examples above will do the trick.

Load data from file in java

I have the following class:
public class DataService {
static <T> void load(Structure structure, String path, DataServiceType dataService) {
//do smth
}
private interface DataServiceType<T> {
//do smth
}
private static class DataServiceInteger implements DataServiceType<Integer> {
//do smth
}
private static class DataServiceString implements DataServiceType<String> {
//do smth
}
}
I want to add there two following methods:
public static void load(Structure<Integer> structure,String path) throws IOException {
load(structure,path,new DataServiceInteger());
}
public static void load(Structure<String> structure,String path) throws IOException {
load(structure,path,new DataServiceString());
}
but both methods have same erasure. How can I achive it without changing methods names?
EDIT
I wasn't accurate. Classes implement DataServiceType have mathod :
void getDataFromString(String in, T out);
(they are paresers)
Reading from file is held in mehod static <T> void load(Structure structure, String path, DataServiceType dataService) from DataService, so M. le Rutte's solution wouldn't be good for me, because I would have to repeat myself. Is it possible to implement berry's soulution for my problem?
As you already found out, due to type erasure the runtime would not be able to distinguish between the different methods. Either the name must be different, or the arguments must be different.
However, you use a static method. My personal choice would to be to use specific instances of a DataService:
public interface DataService<T> {
Structure<T> load(Path path);
}
public StringDataService implements DataService<String> {
public Structure<String> load(Path path) {
...
}
}
public IntDataService implements DataService<Integer> {
public Structure<Integer> load(Path path) {
...
}
}
You cannot. The way type erasure works in Java, is that a 'hidden' (synthetic) method is created by the compiler during compilation which casts the object from some superclass (usually Object) to the correct type. As there are two different types in your example, the Java compiler does not know which to cast since both name and the rest of the parameters match completely.
It might be good practice to name the methods differently either way, as loading a String and loading an integer may not necessarily be handled exactly the same way. For example, you might need to load into memory a list of user input strings: in this case, the string might need to be sanitized first.
As said already, you can't do it exactly as described. However, you could do it by adding generic parameters to the load() method itself, and then making a generic DataServiceClazz type (as oppose to separate DataServiceInteger, DataServiceString classes) that implements your DataServiceType interface:
private static class DataServiceClazz<T> implements DataServiceType<T> { //Replaces DataServiceInteger, DataServiceString, etc.
//do smth
}
public static <T> void load(Structure<T> structure, String path) throws IOException {
load(structure, path, new DataServiceClazz<>());
}
This may not work, depending on your use case, since you won't be able to use different logic based on the type of T - but it's the closest pattern to what you have currently.

How to get a list of all implemented classes in Strategy Pattern?

I want to design a system that allows the user to select from a list of file types to save the file as. I have a class named Word, and an interface named SaveFileType. Every filetype implements SaveFileType which has a saveFile() method. The idea is that when the 'programmer' wants to add a new filetype, none of the code in the application has to be changed.
This is the UML diagram I have made:
The problem that I am facing is the Word class doesn't have the list of all available file types, that I need to display to the user.
Some sample code below:
Word class:
public class Word {
SaveFileAs saveFileAs;
Document currentDocument;
public Word(Document currentDocument) {
this.currentDocument = currentDocument;
}
public void saveFile() {
// Print all available filetypes
// No actual file-saving logic is needed.
}
}
Word97 Class:
public class Word97 implements SaveFileAs {
#Override
public void saveFile(Document currentDocument) {
// Do some Java wizardry here.
System.out.println("Document named '" + currentDocument.getTitle() + "' has been saved as filetype 'Word97' " );
}
}
Main class:
public class Main {
public static void main(String[] args) {
Document notes = new Document("Notes", "This is a note.");
Word wordProgram = new Word(notes);
// saveFile should print out a list of all possible filetypes.
wordProgram.saveFile();
}
}
Strategy is for changing implementation at runtime, you cannot get all implementations. It would be the task of another class. Also you need somehow a method like setStrategy(Strategy) in your Word class, that's why you've chosen the pattern right?
For get all implementations, you could make use of ServiceLoader. I would add an enum in the picture.
So the example codes look like:
method in Word class:
void setSaveFileStrategy(AvailableStrategy strategy){
this.saveFileAs = strategy.strategy();
}
The enum:
enum AvailableStrategy{
Word97( Word97.class),
//.... once new strategy was introduced, you need add an entry here.
WordXml( WordXml.class);
private Class<saveFileAs> strategyClass;
AvailableStrategies(Class<saveFileAs> strategyClass) {
this.strategyClass = strategyClass;
}
saveFileAs strategy() throws IllegalAccessException, InstantiationException {
return strategyClass.newInstance() ;
}
}
I think you know how to get all enum instances (available strategies).
Note that codes were not compiled and tested, just for showing the idea. Exception handlings were ignored.
It would be bad if the Word class knew about all the types. It's the job of another class, even if word uses it. One solution would be to have a new class that maps a string extension to the strategy. And can enumerate those strategies:
public final class DocumentTypeMap implements Iterable<SaveFileAs> {
private final Map<String, SaveFileAs> docTypes = new HashMap<>;
public void register(String extension, SaveFileAs saveFileAs) {
docTypes.put(extension, saveFileAs);
}
public Iterator<SaveFileAs> iterator() {
return docTypes.values().iterator();
}
}
Usage:
DocumentTypeMap map = new DocumentTypeMap();
map.register(".doc", new Word97()); //etc.
Word word = new Word(map); //inject the dependency of a pre-configured map into the word class.
Then when the Word class needs the correct strategy during saving, it can use a method on DocumentTypeMap (not provided here) to get the correct one. I'm thinking that might be by extension.
If you want to be able to add a document type without changing any code, it means that the document type list has to be defined outside your code, in file like a property file and your code has to read the property file to know all available types.
Then you need to add in this property file which class implements how to save a specific document type and you implement a factory which instantiate a class given its name, and a class which associate the right instance according to the chosen type.
For the properties files, you can have entries like:
ext_1=.doc
ext_2=.xml
ext_3=.rtf
class_1=Word97
class_2=WordXML
class_3=RTF ...
A such file is easy to parse to know the types list and which class has to be used to save a document.
To know how to instantiate a class from its name, see the class Class and the method newInstance.
This is an "old way", maybe with injection is there a most up to date solution.
In your UML model, I would add the class which reads the properties file, the class which instantiates a class from its name, and the class which associate the right instance to Word. To model the properties file, maybe an instance objet may be use since a properties file is an instance of ResourceBundle.

Applying static methods to data stored in a subclass

I'm working on a class to access information about a class library stored in a Jar file and run actions customized for each class library. It contains methods to load localized strings, etc. from the Jar file.
public class CodeBundle {
public static String str(String id) {
...
}
...
}
I need to be able to know which library I am trying to load information from, so I want to be able to use subclasses representing each library, for example:
public class JAppFramework extends CodeBundle {
...
}
So now in code that is part of the JApp Framework, I want to be able to call JAppFramework.str("...") to load a string from the JApp Framework resource bundle. And if I have another library, such as TestLibrary, I want to be able to call TestLibrary.str("...") to load a string from Test Library's resource bundle. What I did was have a method defined in CodeBundle called getFile() which would return the Jar file from which the library had been loaded. Then the str() method would use that to load the localized string.
The problem is that the static methods in CodeBundle can only access data stored in the CodeBundle class, not in any of its subclasses, as far as I know.
For various reasons, I can't use "getClass().getResource(name)" to load resources.
Is there any way to do what I'm trying to do?
You may try and use singletons:
public abstract class CodeBundle { // or even an interface
public abstract String str(String id);
}
public final class JAppFramework extends CodeBundle {
private static final CodeBundle INSTANCE = new JAppFramework();
// private constructor
private JAppFramework() {
// whatever
}
// get the instance
public static CodeBundle getInstance() { return INSTANCE; }
// Implement str() here
}
// Create other singletons as needed
In your code:
CodeBundle bundle = JAppFramework.getInstance();
bundle.str(whatever);
Of course, this is an ultra simplistic example. Put whatever fields/methods/constructors/constructor arguments are needed in CodeBundle -- which cannot be instantiated since it is abstract.

Is it possible to find an instance of an object without it being passed to the method?

I have a parser class "MessageParser" which i pass a message which is of type "String" to it for it to be parsed. The parsing method signature for the class is
public void parse(String message);
I need to pass an instance of "Properties" to it but i dont want to change the signature of the method to add a new argument to it. I have been struggling with this for the last couple of days and have tried a couple of options - see Sending in an object of type Object instead of String - Polymorphism
The class that calls the parsing method "ParserManager" knows of the properties object. Is there a way for the MessageParser to find the properties object without it being passed to it?
Edit
Here is some example code.
I would like the "MessageCparser" to access the "prop" object in "ParserManager" without changing anything in the "Parser" interface or the "ParserManager" class. Is this possible?
public interface Parser{
public void parse(String message);
}
public class MessageCParser implements Parser{
public void parse(String message){
MessageObject mobject = (MessageObject)message;
System.out.println("Parsing C" + mobject.getMessage());
}
public void parse(String m){}
}
import java.util.HashMap;
public class ParserManager{
Properties prop = null;
public ParserManager() {
prepare();
prop = new Properties()
}
HashMap parsers = new HashMap();
public void prepare(){
parsers.put("A",new MessageCParser());
}
public void parseMessage(String msgType, String message){
((Parser)parsers.get(msgType)).parse(message);
}
}
Thanks
The most evident solution would be to add a reference to the Properties object as a field in the ParserManager, and then either provide the ParserManager with the properties object as a constructor argument or through a setter-method as shown below:
class ParserManager {
...
Properties props;
public void setParsingProperties(Properties props) {
this.props = props;
}
public void parse(String message) {
// props available here, without being passed as agurment.
}
}
class CallingParserManager {
...
void someMethod() {
...
parserManager.setParsingProperties(propertiesToUse);
parserManager.parse(theString);
...
}
...
}
Looking at your previous question, I'd say it would be fine if you added a setParsingProperties in the Parser interface. The method can be implemented as an empty method for those parser that don't need the properties.
Regarding your edit: No, it's not possible to solve it like that.
MessageObject mobject = (MessageObject) message;
Will only work if MessageObject is a subtype of String (but since String is final (can't be extended) that cannot be the case).
The dirty quick-fix would be to check (with instanceof) if the Parser is an instance of MessageCParser and cast it and then use a MessageCParser specific parse method that takes the Properties as an argument.
Well, there are four ways of getting information, broadly speaking:
It could be part of the state of the object that the method is called on (e.g. it could be passed to the constructor and then retained in a field)
It can be a parameter of the method itself
It could be accessed statically, e.g. via a singleton
It could be accessed via a thread-local variable
All of these can be used with indirection of course - for example, if something else which knows about the Properties is available via one of the above mechanisms, then you can get to that and then find out about the Properties. But you can't just find out the calling object and ask that.
What do you need to do with the Properties in question? Would the Properties vary on a call-by-call basis for the same MessageParser? If so, it really should be a parameter. You say you don't want to change the signature of the method - but if you want to pass more information in, that's exactly what you should do.
If you have only one instance of your "Properties" object, you can use something like the Singleton pattern.
You can also add a reference to the ParserManager somewhere in your MessageParser and then call a method on ParserManager which will return the Properties, but without some code snippets it's impossible to help you further than this.

Resources