need C++ template-like functionality in Java - java

In my program, I've got the following class hierarchy:
public abstract class Effect
{
// ...
}
public class Effect1 extends Effect
{
public static final NAME = "blah blah 1";
// ...
}
public class Effect2 extends Effect
{
public static final NAME = "blah blah 2";
// ...
}
(many more EffectN classes with quite different implementations). Later on, I've got another family of classes using those EffectN's :
public abstract class EffectList
{
protected Effect mEffect;
// ...
}
public class EffectList1 extends EffectList
{
public static final N = Effect1.NAME;
public EffectList1
{
mEffect = new Effect1();
}
// ...
}
public class EffectList2 extends EffectList
{
public static final N = Effect2.NAME;
public EffectList2
{
mEffect = new Effect2();
}
// ...
}
(many more of those EffectListN classes, one for each EffectN).
Now, while the EffectN's really do have quite different implementations, all the EffectListN's are (nearly) identical - the only difference between them is shown above.
Now, had this been C++, all the EffectListN classes would be easily generated with just 1 template, but AFAIK (being quite new to Java) Java generics cannot do this job, can it?
Any suggestions?

Are you trying to create generic way to call constructor? If so this could be done by reflection as long as all implementation would supply the same kind of arguments e.g. default constructor:
class EffectList<EffectType extends Effect> {
public EffectList(Class<EffectType> clazz) {
try {
mEffect = clazz.getConstructor().newInstance();
} catch (Exception ex) {
// suppressing Exceptions - in production code you should handle it better
throw new RuntimeException(ex);
}
// ...
}
// ...
}
then use it like that:
EffectList<Effect1> effectList1 = new EffectList(Effect1.class);
EffectList<Effect2> effectList2 = new EffectList(Effect2.class);
The static field however cannot be handled such way - best you can do is make it an instance variable and obtain the value via reflection as well:
clazz.getDeclaredField("NAME").get(null); // null is used to obtain static fields
Reason why static field cannot be handled is that there would be only one variable shared among all EffectLists (since underneath its only just one class with just compile-time checks added).

I don't know how you would do it with C++, but going off your description, no, Java generics would not be able to handle this.
For one, you have static fields that depend on other static fields defined in the EffectN types. There's nothing in Java which sets a restriction that a type should have a static field. You wouldn't be able to dynamically set
public static final N = SomeEffect.NAME;
Second, because of type erasure, you would not be able to do
public EffectList2
{
mEffect = new SomeEffect(); // assuming SomeEffect is the type parameter
}
you'd need to pass in a Class instance and use reflection to instantiate this type.

Related

Is it possible in java to make generic with unstable number of classes? [duplicate]

I am looking to create a particular type of interface in Java (although this is just as applicable to regular classes). This interface would need to contain some method, say, invoke; it would be called with a varying amount of parameters depending on the generic type arguments supplied.
As an example:
public interface Foo<T...> {
public void invoke(T... args);
}
// In some other class
public static Foo<Float, String, Integer> bar = new Foo<Float, String, Integer>() {
#Override
public void invoke(Float arg1, String arg2, Integer arg3) {
// Do whatever
}
};
To explain, briefly, how this could be used (and provide some context), consider a class Delegator: the class takes a varying number of generic types, and has a single method - invoke, with these parameter types. The method passes on its parameters to an object in a list: an instance of IDelegate, which takes the same generic types. This allows Delegator to choose between several delegate methods (defined inside IDelegate) without having to create a new class for each specific list of parameter types.
Is anything like this available? I have read about variadic templates in C++, but cannot find anything similar in Java. Is any such thing available? If not, what would be the cleanest way to emulate the same data model?
Is anything like this available? I have read about variadic templates
in C++, but cannot find anything similar in Java. Is any such thing
available?
No, this feature is not available in Java.
No, there is nothing like that directly available. However if you use a library with Tuple classes you can simulate it by just making the interface
interface Foo<T> {
void invoke(T t);
}
(This interface is essentially the same as Consumer<T>.)
Then you could do for example
Foo<Tuple<String, Integer, Date, Long>> foo = new Foo<>() {
...
}
You would need a separate Tuple type for each number of parameters. If you have a Tuple class for 4 parameters, but not one for 5, you could squeeze an extra parameter in by using a Pair class.
Foo<Tuple<String, Integer, Date, Pair<Long, BigDecimal>>> foo = ...
By nesting tuple types in this way you get an unlimited number of parameters. However, these workarounds are really ugly, and I would not use them.
Given the context you provided I would recommend using a List as a parameter. If these parameters have something in common, you can restrain your list to <T extends CommonParrent> instead of using List<Object>. If not, you may still want to use marker interface.
Here is an example.
public class Main {
public static void main(String[] args) {
delegate(asList(new ChildOne(1), new ChildTwo(5), new ChildOne(15)));
}
private static <T extends Parent> void delegate(List<T> list) {
list.forEach(item -> {
switch (item.type) {
case ONE: delegateOne((ChildOne) item); break;
case TWO: delegateTwo((ChildTwo) item); break;
default: throw new UnsupportedOperationException("Type not supported: " + item.type);
}
});
}
private static void delegateOne(ChildOne childOne) {
System.out.println("child one: x=" + childOne.x);
}
private static void delegateTwo(ChildTwo childTwo) {
System.out.println("child two: abc=" + childTwo.abc);
}
}
public class Parent {
public final Type type;
public Parent(Type type) {
this.type = type;
}
}
public enum Type {
ONE, TWO
}
public class ChildOne extends Parent {
public final int x;
public ChildOne(int x) {
super(Type.ONE);
this.x = x;
}
}
public class ChildTwo extends Parent {
public final int abc;
public ChildTwo(int abc) {
super(Type.TWO);
this.abc = abc;
}
}
The biggest flaw of this solution is that children have to specify their type via enum which should correspond to the casts in the switch statement, so whenever you change one of these two places, you will have to remember to change the other, because compiler will not tell you this. You will only find such mistake by running the code and executing specific branch so test driven development recommended.

Factory pattern: Accessing child methods

I have two classes CashStore and DrinkStore, both extends from Store. I have a StoreFactory class (returns Store object) to instantiate objects for clients. I want to access methods specific to child classes from these clients. How do I do it without casting? If I used casting, would it break the pattern, since now the clients know about the Child classes?
class Store{
A(){}
B(){}
}
class CashStore{
A(){}
B(){}
C(){}
D(){}
}
//impl for drink store and other stores
class StoreFactory{
public Store getStore(String type){
//return a Store obj based on type DrinkStore or CashStore
}
}
class Client{
StoreFactory fac;
public Client(){
fac = new StoreFactory();
Store s = fac.getStore("cash");
s.C(); //requires a cast
}
}
Does casting break my pattern?
Factory pattern is used to decouple from runtime type. For example, when it's platform- or layout-specific, and you don't want your client code to mess with it. In your case you do need an exact type, so it seems factory pattern isn't a good choice. Consider using simple static methods, like:
class Stores {
static CashStore createCashStore() {
return new CashStore();
}
static DrinkStore createDrinkStore() {
return new DrinkStore();
}
}
So basically you need to access child specific methods without casting. That's the whole purpose of Visitor pattern.
You can switch between different child by using method overloading. I have given an example below, you would need to adapt that to fit into your code. And also you should take out the business logic from the constructor (of Client) and implement them inside methods.
public class Client{
public void doSomething(CashStore cs){
cs.c();
//you can call methods specific to CashStore.
}
public void doSomething(DrinkStore ds){
ds.e();
//you can call methods specific to DrinkStore.
}
}
I want to access methods specific to child classes from these clients.
How do I do it without casting?
If you know the expected type, then you can use generics to avoid casting:
interface Store {
}
class WhiskeyStore implements Store {
}
class VodkaStore implements Store {
}
class StoreFactory {
<T extends Store> T getStore(Class<T> clazz) {
try {
// I use reflection just as an example, you can use whatever you want
return clazz.getConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Cannot create store of type: " + clazz, e);
}
}
}
public final class Example {
public static void main(String[] args) {
WhiskeyStore whiskeyStore = new StoreFactory().getStore(WhiskeyStore.class);
VodkaStore vodkaStore = new StoreFactory().getStore(VodkaStore.class);
}
}

Getting behavior of Java's Class<? extends Map> in .NET

I have a generic class in java defined as:
public static class KeyCountMap<T>
{
private Map<T, MutableInt> map = new LinkedHashMap<T, MutableInt>();
// ... rest of the properties...
public KeyCountMap()
{ }
#SuppressWarnings({ "unchecked", "rawtypes" })
public KeyCountMap(Class<? extends Map> mapType) throws InstantiationException, IllegalAccessException
{
map = mapType.newInstance();
}
//... rest of the methods...
}
I have defined same class in .NET as:
public static class KeyCountMap<T>
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
// ... rest of properties...
public KeyCountMap()
{ }
public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>
{
obj = new T(); // Unable to define new instance of T
map = obj; // Unable to convert T to base class
}
}
And then a method is defined to sort map of type KeyCountMap<T> by value in the descending order . The method is defined as:
public static KeyCountMap<T> SortMapByDescendValue<T>(KeyCountMap<T> _map)
{
List<KeyValuePair<T, MutableInt>> _list = new List<KeyValuePair<T, MutableInt>>(_map.EntrySet());
// whereas _map.EntrySet() return of type HashSet<KeyValuePair<T, MutableInt>>
_list = _list.OrderByDescending(_x => _x.Value).ToList();
KeyCountMap<T> _result = new KeyCountMap<T>();
foreach (KeyValuePair<T, MutableInt> _entry in _list)
{
_result.Put(_entry.Key, _entry.Value);
}
return _result;
}
How can I get corrected the class defined in .NET ?
I assume you know Java erases any generic type information after compiling (there's metadata for variables, but actual objects are void of generic type information). Moreover, your code is not type safe:
#SuppressWarnings({ "unchecked", "rawtypes" })
You're using this because you're creating a non-parameterized instance of Map.
In .NET, you don't get around the type system like this, because generic type information is kept and used at runtime.
Let's see your C# code:
public static class KeyCountMap<T>
A static class in C# is a class that cannot be instanced, it's used for its static members alone. I think you don't want this. Perhaps KeyCountMap is a static nested class in Java, as opposed to an inner class.
In C#, you don't have inner classes. Nested classes don't share data with an instance of the containing class, it's as if the name of the containing class is part of the namespace for the nested class. So, you don't need, and actually don't want, the static keyword here.
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
In .NET, Dictionary is a class. To keep the intent, you should use IDictionary, the corresponding interface, as the type for the map field.
// ... rest of properties...
public KeyCountMap()
{ }
public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>
Why the void return type, isn't this a constructor?
In C#, constructors can't be generic. You probably want a Type.
Your C# code just doesn't make sense, so here's what you could do:
public KeyCountMap(Type dictionaryType)
{
if (!typeof(IDictionary<T, MutableInt>).IsAssignableFrom(dictionaryType))
{
throw new ArgumentException("Type must be a IDictionary<T, MutableInt>", nameof(dictionaryType));
}
map = (IDictionary<T, MutableInt>)Activator.CreateInstance(dictionaryType);
}
}
We're checking the type before creating an instance. If we didn't, we would create an instance, the cast would fail and the assignment wouldn't even happen, so the new instance would just be garbage.
It may be that the actual instance will be a proxy; if so, you may not want to check the type before creating an instance.
You can't just copy-paste Java as C# (or vice-versa) and expect to make just a few changes until it works, for some definition of works, e.g. it compiles. The languages are not that similar, and chances are that too many subtle things are wrong.
This approach might be fun at first, but you'll stumble so often it will soon stop being any fun at all. You should learn the basics and understand the way things are done in the target language before you start translating code line-by-line. Many times, you may find that something you had to do in one environment already exists in the other or vice-versa, or that something may take more or less steps to do in the other, etc.
In this particular case, Java made Class be a generic class, while .NET kept Type a non-generic class. In .NET only interfaces and delegates may state generic type covariance or contravariance. This is rather restrictive anyway, if Type was generic, the intended uses could be either covariant or contravariant. But remember that in Java, a generic Class<T> at runtime is as good as Class, it only has any value at compile time and you can tell the compiler you know better anyway, just like you did.
There are two problems. First, you need to tell the compiler that T has a parameterless constructor, so you can call new T(). You can do that by providing the new() argument to the class definition.
You also have to tell the compiler that T is actually the dictionary you are trying to assign, so we have to extend the class a little more:
public class KeyCountMap<K>
{
private Dictionary<K, MutableInt> map = new Dictionary<K, MutableInt>();
// ... rest of properties...
Note that K is the key type of the dictionary, which you didn't specify yet.
Second, the T in your method can be another T than in your class. Omitting that will do the trick:
public void Map()
{
var obj = new Dictionary<K, MutableInt>(); // Unable to define new instance of T
map = obj; // Unable to convert T to base class
}
Maybe this is what you want?
public class KeyCountMap<T>
where T : new()
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
// ... rest of properties...
public KeyCountMap()
{ }
public KeyCountMap(T obj)
{
obj = new T();
map = (Dictionary<T, MutableInt>)(object)obj;
}
}

In Java, can I specify any amount of generic type parameters?

I am looking to create a particular type of interface in Java (although this is just as applicable to regular classes). This interface would need to contain some method, say, invoke; it would be called with a varying amount of parameters depending on the generic type arguments supplied.
As an example:
public interface Foo<T...> {
public void invoke(T... args);
}
// In some other class
public static Foo<Float, String, Integer> bar = new Foo<Float, String, Integer>() {
#Override
public void invoke(Float arg1, String arg2, Integer arg3) {
// Do whatever
}
};
To explain, briefly, how this could be used (and provide some context), consider a class Delegator: the class takes a varying number of generic types, and has a single method - invoke, with these parameter types. The method passes on its parameters to an object in a list: an instance of IDelegate, which takes the same generic types. This allows Delegator to choose between several delegate methods (defined inside IDelegate) without having to create a new class for each specific list of parameter types.
Is anything like this available? I have read about variadic templates in C++, but cannot find anything similar in Java. Is any such thing available? If not, what would be the cleanest way to emulate the same data model?
Is anything like this available? I have read about variadic templates
in C++, but cannot find anything similar in Java. Is any such thing
available?
No, this feature is not available in Java.
No, there is nothing like that directly available. However if you use a library with Tuple classes you can simulate it by just making the interface
interface Foo<T> {
void invoke(T t);
}
(This interface is essentially the same as Consumer<T>.)
Then you could do for example
Foo<Tuple<String, Integer, Date, Long>> foo = new Foo<>() {
...
}
You would need a separate Tuple type for each number of parameters. If you have a Tuple class for 4 parameters, but not one for 5, you could squeeze an extra parameter in by using a Pair class.
Foo<Tuple<String, Integer, Date, Pair<Long, BigDecimal>>> foo = ...
By nesting tuple types in this way you get an unlimited number of parameters. However, these workarounds are really ugly, and I would not use them.
Given the context you provided I would recommend using a List as a parameter. If these parameters have something in common, you can restrain your list to <T extends CommonParrent> instead of using List<Object>. If not, you may still want to use marker interface.
Here is an example.
public class Main {
public static void main(String[] args) {
delegate(asList(new ChildOne(1), new ChildTwo(5), new ChildOne(15)));
}
private static <T extends Parent> void delegate(List<T> list) {
list.forEach(item -> {
switch (item.type) {
case ONE: delegateOne((ChildOne) item); break;
case TWO: delegateTwo((ChildTwo) item); break;
default: throw new UnsupportedOperationException("Type not supported: " + item.type);
}
});
}
private static void delegateOne(ChildOne childOne) {
System.out.println("child one: x=" + childOne.x);
}
private static void delegateTwo(ChildTwo childTwo) {
System.out.println("child two: abc=" + childTwo.abc);
}
}
public class Parent {
public final Type type;
public Parent(Type type) {
this.type = type;
}
}
public enum Type {
ONE, TWO
}
public class ChildOne extends Parent {
public final int x;
public ChildOne(int x) {
super(Type.ONE);
this.x = x;
}
}
public class ChildTwo extends Parent {
public final int abc;
public ChildTwo(int abc) {
super(Type.TWO);
this.abc = abc;
}
}
The biggest flaw of this solution is that children have to specify their type via enum which should correspond to the casts in the switch statement, so whenever you change one of these two places, you will have to remember to change the other, because compiler will not tell you this. You will only find such mistake by running the code and executing specific branch so test driven development recommended.

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;
}
}
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.
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;
}
}
You can use enum as well, just like below :
interface CodecInterface {
}
class CodecA implements CodecInterface {
}
class CodecB implements CodecInterface {
}
class CodecC implements CodecInterface {
}
enum CodecType {
codecA {
public CodecInterface create() {
return new CodecA();
}
},
codecB {
public CodecInterface create() {
return new CodecB();
}
},
codecC {
public CodecInterface create() {
return new CodecC();
}
};
public CodecInterface create() {
return null;
}
}
class CodecFactory {
public CodecInterface newInstance(CodecType codecType) {
return codecType.create();
}
}

Categories