Adding a protected constructor to allow subclasses provide different implementations - java

I have the following interface (some methods ommited for simplicity):
public interface Container{
public void put(String s, Object o);
public Object get(String s);
}
and its implementation:
public class ContainerImpl implements Container{
private Map<Stirng, Object> m;
public ContainerImpl(){
m = new HashMap<>();
}
//This constructor is used in the case if a client is not satisfied
//by the HashMap, e.g. in case of Enum it's better to use EnumMap
protected ContainerImpl(Map<String, Object> m){
this.m = m;
}
public void put(String s, Object o){
m.put(s, o);
}
public Object get(String s){
m.get(s);
}
}
My question is about if providing such a protected constructor contraries to incapsulation. In fact we give to clients some knowledge that internally we use Map. If the dataStructure changed, we'll have to perform a conversion from the map passed as a parameter which may probably cause some bugs, I think.

if providing such a protected constructor contraries to incapsulation.
You are right, it does contradicts incapsulation behavior of ContainerImpl.
IMHO this is a design decision; whether class is designed to enforce incapsulation or to expose to client's/caller's for supporting varities of constructs.
For example:
A: ContainerImpl with only default-constructor implies that internal storage of Container is completely governed by it's concrete-implementation and caller cannot choose different storage.
B:
And ContainerImpl with
protected ContainerImpl(Map<String, Object> m)
implies that caller can choose the nature of Map based storage i.e. TreeMap, HashMap, LinkedHashMap or a custom implementation.
Decision on choosing one of the above approached would be based on client's need and nature.

You have responsibilities of creation, use and encapsulation of underlying Map in a single class.
If you want to follow SRP, try leaving the only public constructor which accepts Map as argument, use factories or descendants to encapsulate data:
/**
* #param m - storage model. Should not be modified after call.
*/
public ContainerImpl(Map<String, Object> m){
this.m = m;
}
/** A new instance with default storage model */
public static ContainerImpl createDefault() {
// Storage reference is isolated
return new ContainerImpl(new HashMap<>());
}
Alternatively, delete all constructors and provide:
protected abstract Map<String, Object> getStorage();

I would suggest to use something like this:
protected ContainerImpl(Map<String, Object> m){
this(); //default constructor, instantiates internal map
this.m.putAll(m); // copy all values
}
This way you will not affect encapsulation, but you will provide some convenience. As an alternative you could provide a factory method like this:
protected ContainerImpl create(Map<String, Object> m){
ContainerImpl impl = new ContainerImpl(); //default constructor, instantiates internal map
impl.m.putAll(m); // copy all values
return impl;
}

Related

How to write a enum that would take generics variable

I have a usecase to create a Singleton cache using enum. The key and value of the cache should be generic variable.
Enum in java do not directly take generic variables. Not perfectly sure if that can be done if implementing an interface. Although it works to an extent if we provide the datatype in place of generics variables. To explain this. The below code is fine without compilation error.
public enum MyCache implements Cache<String, String> {
INSTANCE;
#Override
public void putIntoMyCache(String dK, String dV) {
domainDataCache.put(dK, dV);
}
#Override
public Optional<String> getFromMyCache(String dK) {
return domainDataCache.get(dK);
}
private DomainDataCache<String, String> domainDataCache = new DomainDataCache();
}
public interface Cache<Key,Value> {
public void putIntoLgiCache(Key dK, Value dV);
public Optional<Value> getFromLgiCache(Key dK);
}
In the above code we implemented Cache interface using
Cache<String, String>
which works. But I need to have a
cache<Key,Value>
whose key and value needs to be generic variable,
I have no clue if this is possible in java!!
Thanks in advance Guys!!

Java, parent static method returning child type

I'm new to java and Generics so please bear with me. I don't even know if this is possible. I've looked around and although there seem to be a few posts about this here and there I haven't found one that addresses my specific case clearly enough for me to understand what to do.
I basically have a static method in the parent class and would like it to return various types based on which child calls it. The trick here is that said child class that is returned also needs to be instantiated within the method.
Here's what I mean:
public class Parent {
public String value;
public Parent(String value)
{
this.value = value;
}
public static <T extends Parent> T load(DataStorage data, String key)
{
T inst = new ???(data.getValue(key));
return inst;
}
}
public class Child extends Parent {
}
Child child = Child.load(dataStore, "key"); // random dataStore instance
I'm not sure where to go from here. What do I use in place of ??? which should be whichever child (or Parent) runs the load() ? Do I need to also do something along the lines of Child.<Child>load()?
I'm open to alternative designs if you feel I'm mistaking in trying to do things like this. I don't like the idea of having to play around with Reflection in this situation (feels a little hacky)
Thanks in advance, I really appreciate it.
I guess what you want would be possible if Java didn't have type erasure and had 'constructor with parameter constraint' for generic types(like .net, but it has constraint for parameterless constructors only).
Maybe those two suits your needs:
If type of Child based on some selection criteria(e.g. an enumaration) I would go with a factory pattern like:
public class ParentFactory {
Parent create(SomeEnum t, DataStore dataStore, String key) {
switch (t) {
case SomeEnum.Child1Related:
return new Child1(dataStore.get(key));
...
}
}
}
But if creation is completely irrelevant(which is not in most cases), you can just define an init method in Parent and have initializer code there:
abstract class Parent {
String value;
Parent() {}
protected void init(String s) { this.value = s; }
static <T extends Parent> void initialize(DataStore data, String key, T t) {
t.init(data.getValue(key));
}
Child c = new Child();
Parent.init(dataStore, key, c);
You can make init method as private if you want to prohibit childs to intercept that call.
Honestly, I favor first one much more. Second one is a little ugly :)
It sounds like the thing you're looking for is a strongly-typed key object, which can associate a string with the corresponding child type. What I've done in the past is simply write a class for this key type.
Assuming your datastore looks something like this:
public interface DataStore {
DataItem get(String key);
}
And your various child classes look like this:
public final class Child1 extends Parent {
public Child1(DataItem dataItem) {
...
}
...
}
Your Key type could look like this:
/**
* Represents a way to construct an object from a {#link DataItem}.
*
* #param <T> the type of the object to construct.
*/
public final class Key<T extends Parent> {
private final String key;
// Assuming Java 8 Function. If you're using Java 7 or older,
// you can define your own Function interface similarly.
private final Function<DataItem, T> factoryFunction;
public Key(String key, Function<String, T> factoryFunction) {
this.key = checkNotNull(key);
this.factoryFunction = checkNotNull(factoryFunction);
}
public String key() {
return this.key;
}
public T constructFrom(DataItem dataItem) {
if (!key.equals(dataItem.getKey())) {
throw new IllegalStateException(
"DataItem is not valid for key " + key);
}
return factoryFunction.apply(dataItem);
}
}
Then you'll probably want a collection of well-known keys:
/** Well-known {#link Key} instances. */
public final class Keys {
private Keys() {} // static class
/** Key for {#link Child1}. */
public static final Key<Child1> FIRST_CHILD
= new Key<>("child1", Child1::new);
/** Key for {#link Child2}. */
public static final Key<Child2> SECOND_CHILD
= new Key<>("child2", Child2::new);
// etc.
}
Then you can define classes that work with these strongly-typed key instances:
public final class Loader {
private final DataStore dataStore;
public Loader(DataStore dataStore) {
this.dataStore = checkNotNull(dataStore);
}
public <T extends Parent> T load(Key<T> dataKey) {
return key.constructFrom(dataStore.get(dataKey.key()));
}
...
}
Note that this example still works even if you don't have Java 8 -- you'll just need to use an anonymous inline class to construct the child, rather than a lambda expression:
public static final Key<Child1> FIRST_CHILD =
new Key<Child1>("child1", new Function<DataItem, Child1>() {
#Override public Child1 apply(DataItem dataItem) {
return new Child1(dataItem);
}
});
You could of course use reflection for this part if you want, but manually writing the supplier functions will be faster. (Or, if you want the best of both worlds, you could use something like cglib's FastClass.) If you wanted to, you could also make the Key class abstract, so that you would subclass it and override a factory method rather than using a Function.
If you want to, you can merge the Loader type into your Parent class, but I wouldn't, since I think that would violate the Single Responsibility Principle -- typically you want the job of loading domain objects from storage to be separate from the domain objects themselves.
Hopefully that helps!

Using enum to implement multitons in Java

I would like to have a limited fixed catalogue of instances of a certain complex interface. The standard multiton pattern has some nice features such as lazy instantiation. However it relies on a key such as a String which seems quite error prone and fragile.
I'd like a pattern that uses enum. They have lots of great features and are robust. I've tried to find a standard design pattern for this but have drawn a blank. So I've come up with my own but I'm not terribly happy with it.
The pattern I'm using is as follows (the interface is highly simplified here to make it readable):
interface Complex {
void method();
}
enum ComplexItem implements Complex {
ITEM1 {
protected Complex makeInstance() { return new Complex() { ... }
},
ITEM2 {
protected Complex makeInstance() { return new Complex() { ... }
};
private Complex instance = null;
private Complex getInstance() {
if (instance == null) {
instance = makeInstance();
}
return instance;
}
protected void makeInstance() {
}
void method {
getInstance().method();
}
}
This pattern has some very nice features to it:
the enum implements the interface which makes its usage pretty natural: ComplexItem.ITEM1.method();
Lazy instantiation: if the construction is costly (my use case involves reading files), it only occurs if it's required.
Having said that it seems horribly complex and 'hacky' for such a simple requirement and overrides enum methods in a way which I'm not sure the language designers intended.
It also has another significant disadvantage. In my use case I'd like the interface to extend Comparable. Unfortunately this then clashes with the enum implementation of Comparable and makes the code uncompilable.
One alternative I considered was having a standard enum and then a separate class that maps the enum to an implementation of the interface (using the standard multiton pattern). That works but the enum no longer implements the interface which seems to me to not be a natural reflection of the intention. It also separates the implementation of the interface from the enum items which seems to be poor encapsulation.
Another alternative is to have the enum constructor implement the interface (i.e. in the pattern above remove the need for the 'makeInstance' method). While this works it removes the advantage of only running the constructors if required). It also doesn't resolve the issue with extending Comparable.
So my question is: can anyone think of a more elegant way to do this?
In response to comments I'll tried to specify the specific problem I'm trying to solve first generically and then through an example.
There are a fixed set of objects that implement a given interface
The objects are stateless: they are used to encapsulate behaviour only
Only a subset of the objects will be used each time the code is executed (depending on user input)
Creating these objects is expensive: it should only be done once and only if required
The objects share a lot behaviour
This could be implemented with separate singleton classes for each object using separate classes or superclasses for shared behaviour. This seems unnecessarily complex.
Now an example. A system calculates several different taxes in a set of regions each of which has their own algorithm for calculting the taxes. The set of regions is expected to never change but the regional algorithms will change regularly. The specific regional rates must be loaded at run time via remote service which is slow and expensive. Each time the system is invoked it will be given a different set of regions to calculate so it should only load the rates of the regions requested.
So:
interface TaxCalculation {
float calculateSalesTax(SaleData data);
float calculateLandTax(LandData data);
....
}
enum TaxRegion implements TaxCalculation {
NORTH, NORTH_EAST, SOUTH, EAST, WEST, CENTRAL .... ;
private loadRegionalDataFromRemoteServer() { .... }
}
Recommended background reading: Mixing-in an Enum
Seems fine. I would make initialization threadsafe like this:
enum ComplexItem implements Complex {
ITEM1 {
protected Complex makeInstance() {
return new Complex() { public void method() { }};
}
},
ITEM2 {
protected Complex makeInstance() {
return new Complex() { public void method() { }}
};
private volatile Complex instance;
private Complex getInstance() {
if (instance == null) {
createInstance();
}
return instance;
}
protected abstract Complex makeInstance();
protected synchronized void createInstance() {
if (instance == null) {
instance = makeInstance();
}
}
public void method() {
getInstance().method();
}
}
The modifier synchronized only appears on the createInstance() method, but wraps the call to makeInstance() - conveying threadsafety without putting a bottleneck on calls to getInstance() and without the programmer having to remember to add synchronized to each to makeInstance() implementation.
This works for me - it's thread-safe and generic. The enum must implement the Creator interface but that is easy - as demonstrated by the sample usage at the end.
This solution breaks the binding you have imposed where it is the enum that is the stored object. Here I only use the enum as a factory to create the object - in this way I can store any type of object and even have each enum create a different type of object (which was my aim).
This uses a common mechanism for thread-safety and lazy instantiation using ConcurrentMap of FutureTask.
There is a small overhead of holding on to the FutureTask for the lifetime of the program but that could be improved with a little tweaking.
/**
* A Multiton where the keys are an enum and each key can create its own value.
*
* The create method of the key enum is guaranteed to only be called once.
*
* Probably worth making your Multiton static to avoid duplication.
*
* #param <K> - The enum that is the key in the map and also does the creation.
*/
public class Multiton<K extends Enum<K> & Multiton.Creator> {
// The map to the future.
private final ConcurrentMap<K, Future<Object>> multitons = new ConcurrentHashMap<K, Future<Object>>();
// The enums must create
public interface Creator {
public abstract Object create();
}
// The getter.
public <V> V get(final K key, Class<V> type) {
// Has it run yet?
Future<Object> f = multitons.get(key);
if (f == null) {
// No! Make the task that runs it.
FutureTask<Object> ft = new FutureTask<Object>(
new Callable() {
public Object call() throws Exception {
// Only do the create when called to do so.
return key.create();
}
});
// Only put if not there.
f = multitons.putIfAbsent(key, ft);
if (f == null) {
// We replaced null so we successfully put. We were first!
f = ft;
// Initiate the task.
ft.run();
}
}
try {
/**
* If code gets here and hangs due to f.status = 0 (FutureTask.NEW)
* then you are trying to get from your Multiton in your creator.
*
* Cannot check for that without unnecessarily complex code.
*
* Perhaps could use get with timeout.
*/
// Cast here to force the right type.
return type.cast(f.get());
} catch (Exception ex) {
// Hide exceptions without discarding them.
throw new RuntimeException(ex);
}
}
enum E implements Creator {
A {
public String create() {
return "Face";
}
},
B {
public Integer create() {
return 0xFace;
}
},
C {
public Void create() {
return null;
}
};
}
public static void main(String args[]) {
try {
Multiton<E> m = new Multiton<E>();
String face1 = m.get(E.A, String.class);
Integer face2 = m.get(E.B, Integer.class);
System.out.println("Face1: " + face1 + " Face2: " + Integer.toHexString(face2));
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
In Java 8 it is even easier:
public class Multiton<K extends Enum<K> & Multiton.Creator> {
private final ConcurrentMap<K, Object> multitons = new ConcurrentHashMap<>();
// The enums must create
public interface Creator {
public abstract Object create();
}
// The getter.
public <V> V get(final K key, Class<V> type) {
return type.cast(multitons.computeIfAbsent(key, k -> k.create()));
}
}
One thought about this pattern: the lazy instantiation isn't thread safe. This may or may not be okay, it depends on how you want to use it, but it's worth knowing. (Considering that enum initialisation in itself is thread-safe.)
Other than that, I can't see a simpler solution that guarantees full instance control, is intuitive and uses lazy instantiation.
I don't think it's an abuse of enum methods either, it doesn't differ by much from what Josh Bloch's Effective Java recommends for coding different strategies into enums.

Map from property of entry to entry

I often see lists of objects in java holding beans whose objects are picked by inspecting an ID field, i.e.
List<BeanObj> list = …
BeanObj myObj = null;
for(BeanObj b : list)
if(b.getId().equals(whatIAmLookingFor)){
myObj = b;
break;
}
(The second variant of this is storing the objects in Hibernate and retrieve them by SQL.)
Using a Map interface would really be sensible here, but there are difficulties, i.e.
the key field may be changed (in general, or even concurrently)
the key may be non-trivial to reach (think of b.getRoot().getAttribute("id").equals(…)
Have there been approaches to address this in a more efficient way, like implementing a
SpecialMap<String, BeanObj>("id") // use String getId() on BeanObj
or even
SpecialMap<String, BeanObj>("getRoot().getAttribute({0})", "id")
// use String getAttribute("id") on result of getRoot()
with add() instead put() which makes use of the id getter function to build its internal map? Probably this map will require the mapped objects to implement some interface to allow the map being notified of updates on the id field.
Perhaps the map could also take care that changing the ID of an object to an ID of an existing object is either not possible or results in dropping the object that previously had that ID.
You can manage the functionnal aspect of adding element to your map by using guava utilities:
import com.google.common.base.Function;
public class SpecialMap<K, V> extends HashMap<K, V>{
private Function<V, K> function;
public SpecialMap(Function<V, K> function) {
this.function = function;
}
public void add(V value) {
K key = function.apply(value);
this.put(key, value);
}
public static void main(String[] args) {
SpecialMap<String, BeanObj> specialMap = new SpecialMap<String, BeanObj>(new Function<BeanObj, String>() {
#Override
public String apply(BeanObj arg) {
return arg.getRoot().getAttribute("id");
}
});
specialMap.add(new BeanObj());
}
}
In this example, the function will map your bean type to a string key.

How to use Java Enums being DRY with only a single parameter different between instantiations?

I'm trying to figure out if there is a clean way of doing this. I want to design an ENUM to maintain a list of constant values for different components in my application. Each enum would have the same configuration and same parameters, but would differ at the very least by component name.
In a normal Java class, I could build all the basic logic/code in a base abstract class, and have each component constants extend the abstract class and populate only its own pertinent information. However, Java enums do not allow extending existing classes.
Is there something I can do to avoid having to either push all my constants in a single Enum (ugggg!) or recreate the same enum class each time for each differing component? Definitely not DRY in that case, but I do not know how to avoid the issue.
For a quick use-case example off the top of my head. Say I want to keep a list of all my request mappings in an Enum for use elsewhere in my application. Fairly easy to design an enum that says:
public enum RequestMapping {
INDEX("index"),
GET_ALL_USERS( "getAllUsers");
private String requestMapping = "/users";
private String path;
RatesURI( String path ){
this.path = path;
}
public String getRequestMapping(){
return requestMapping;
}
public String getPath(){
return path;
}
public String getFullRequestPath(){
return requestMapping + "/" + path;
}
}
It becomes easy to use RequestMapping.GET_ALL_USERS.getFullRequestPath().
Now if I want to create this enum on a per-controller basis, I would have to recreate the entire Enum class and change the "requestMapping" value for each one. Granted, this enum has nearly no code in it, so duplicating it would not be difficult, but the concept still remains. The theoretical "clean" way of doing this would be to have an abstract AbstractRequestMapping type that contained all the methods, including an abstract getRequestMapping() method, and only have the extending Enums implement the controller-specific getReqeuestMapping(). Of course, since Enums cannot be extended, I can't think of a non DRY way of doing this.
Have you considered extending a class that takes Enum as a generic parameter? It is an amazingly flexible mechanism.
public class Entity<E extends Enum<E> & Entity.IE> {
// Set of all possible entries.
// Backed by an EnumSet so we have all the efficiency implied along with a defined order.
private final Set<E> all;
public Entity(Class<E> e) {
// Make a set of them.
this.all = Collections.unmodifiableSet(EnumSet.<E>allOf(e));
}
// Demonstration.
public E[] values() {
// Make a new one every time - like Enum.values.
E[] values = makeTArray(all.size());
int i = 0;
for (E it : all) {
values[i++] = it;
}
return values;
}
// Trick to make a T[] of any length.
// Do not pass any parameter for `dummy`.
// public because this is potentially re-useable.
public static <T> T[] makeTArray(int length, T... dummy) {
return Arrays.copyOf(dummy, length);
}
// Example interface to implement.
public interface IE {
#Override
public String toString();
}
}
class Thing extends Entity<Thing.Stuff> {
public Thing() {
super(Stuff.class);
}
enum Stuff implements Entity.IE {
One,
Two;
}
}
You can pass the nature of your implementation up to the parent class in many different ways - I use enum.class for simplicity.
You can even make the enum implement an interface as you can see.
The values method is for demonstration only. Once you have access to the Set<E> in the parent class you can provide all sorts of functionality just by extending Entity.
I will probably split the responsibilities into two parts:
Logic about how a request is structured, and put that into an immutable class.
Actual configurations of each request, stored in enums
The enum will then store an instance of that class, you can add new methods to the class, without modifying the different enums, as long as the constructor remains the same. Note that the class must be immutable, or your enum will not have a constant value.
You can use it like the:
ServiceRequest.INDEX.getRequest().getFullRequestPath()
With these classes:
public interface RequestType {
Request getRequest();
}
public class Request {
private final String requestMapping;
private final String path;
RatesURI(String requestMapping, String path){
this.requestMappint = requestMapping;
this.path = path;
}
public String getRequestMapping(){
return requestMapping;
}
public String getPath(){
return path;
}
public String getFullRequestPath(){
return requestMapping + "/" + path;
}
}
public enum ServiceRequest implements RequestType {
INDEX("index"),
GET_ALL_USERS( "getAllUsers");
private final Request;
ServiceRequest(String path) {
request = new Request("users/", path)
}
public String getRequest{
return request;
}
}
I think what you should be asking yourself is really why you want to use enums for this. First we can review some of the points that make Java enumerated types what they are.
Specifically
A Java enum is a class that extends java.lang.Enum.
Enum constants are static final instances of that class.
There is some special syntax to use them but that is all they boil down to. Because instantiating new Enum instances is disallowed outside of the special syntax (even with reflection, enum types return zero constructors) the following is also ensured to be true:
They can only be instantiated as static final members of the enclosing class.
The instances are therefore explicitly constant.
As a bonus, they are switchable.
What it really boils down to is what it is about the enums that makes them preferable over a simpler OOP design here. One can easily create a simple RequestMapping class:
/* compacted to save space */
public class RequestMapping {
private final String mapping, path;
public RequestMapping(String mapping, String path) {
this.mapping = mapping; this.path = path;
}
public String getMapping() {
return mapping; }
public String getPath() {
return path; }
public String getFullRequestPath() {
return mapping + "/" + path;
}
}
Which can easily be extended to break down the repeated code:
public class UserMapping extends RequestMapping {
public UserMapping(String path) {
super("/users", path);
}
}
/* where ever appropriate for the constants to appear */
public static final RequestMapping INDEX = new UserMapping("index"),
GET_ALL_USERS = new UserMapping("getAllUsers");
But I assume there is something about enums that is attractive to your design, such as the principle that instances of them are highly controlled. Enums cannot be created all willy-nilly like the above class can be. Perhaps it's important that there be no plausible way for spurious instances to be created. Of course anybody can come by and write in an enum with an invalid path but you can be pretty sure nobody will do it "by accident".
Following the Java "static instances of the outer class" enum design, an access modifier structure can be devised that generally abides by the same rule set as Enum. There are, however, two problems which we can't get around easily.
Two Problems
Protected modifier allows package access.
This can easily be surmounted initially by putting the Enum-analog in its own package. The problem becomes what to do when extending. Classes in the same package of the extended class will be able to access constructors again potentially anywhere.
Working with this depends on how stringent you want to be on creating new instances and, conversely, how clear the design ends up. Can't be a whole mess of scopes just so only a few places can do the wrong thing.
Static members are not polymorphic.
Enum surmounts this by not being extendable. Enum types have a static method values that appears "inherited" because the compiler inserts it for you. Being polymorphic, DRY and having some static features means you need instances of the subtype.
Defeating these two issues depends on how stringent you want your design to be and, conversely, how readable and stable you want your implementation to be. Trying to defy OOP principles will get you a design that's hard to break but totally explodes when you call that one method in a way you aren't supposed to (and can't prevent).
First Solution
This is almost identical to the Java enum model but can be extended:
/* 'M' is for 'Mapping' */
public abstract class ReturnMapping<M extends ReturnMapping> {
/* ridiculously long HashMap typing */
private static final HashMap <Class<? extends ReturnMapping>, List<ReturnMapping>>
VALUES = new HashMap<Class<? extends ReturnMapping>, List<ReturnMapping>>();
private final String mapping, path;
protected Mapping(String mapping, String path) {
this.mapping = mapping;
this.path = path;
List vals = VALUES.get(getClass());
if (vals == null) {
vals = new ArrayList<M>(2);
VALUES.put(getClass(), vals);
}
vals.add(this);
}
/* ~~ field getters here, make them final ~~ */
protected static <M extends ReturnMapping> List<M>(Class<M> rm) {
if (rm == ReturnMapping.class) {
throw new IllegalArgumentException(
"ReturnMapping.class is abstract");
}
List<M> vals = (List<M>)VALUES.get(rm);
if (vals == null) {
vals = new ArrayList<M>(2);
VALUES.put(rm, (List)vals);
}
return Collections.unmodifiableList(vals);
}
}
Now extending it:
public final class UserMapping extends ReturnMapping<UserMapping> {
public static final UserMapping INDEX = new UserMapping("index");
public static final UserMapping GET_ALL_USERS = new UserMapping("getAllUsers");
private UserMapping(String path) {
super("/users", path);
}
public static List<UserMapping> values() {
return values(UserMapping.class);
}
}
The huge static HashMap allows almost all of the values work to be done statically in the superclass. Since static members are not properly inherited this is the closest you can get to maintaining a list of values without doing it in the subclass.
Note there are two problems with the Map. The first is that you can call the values with ReturnMapping.class. The map should not contain that key (the class is abstract and the map is only added to in the constructor) so something needs to be done about it. Instead of throwing an exception you could also insert a "dummy" empty list for that key.
The other problem is that you can call values on the superclass before the instances of the subclass are instantiated. The HashMap will return null if this is done before the subclass is accessed. Static problem!
There is one other major problem with this design because the class can be instantiated externally. If it's a nested class, the outer class has private access. You can also extend it and make the constructor public. That leads to design #2.
Second Solution
In this model the constants are an inner class and the outer class is a factory for retrieving new constants.
/* no more generics--the constants are all the same type */
public abstract class ReturnMapping {
/* still need this HashMap if we want to manage our values in the super */
private static final HashMap <Class<? extends ReturnMapping>, List<Value>>
VALUES = new HashMap<Class<? extends ReturnMapping>, List<Value>>();
public ReturnMapping() {
if (!VALUES.containsKey(getClass())) {
VALUES.put(getClass(), new ArrayList<Value>(2));
}
}
public final List<Value> values() {
return Collections.unmodifiableList(VALUES.get(getClass()));
}
protected final Value newValue(String mapping, String path) {
return new Value(getClass(), mapping, path);
}
public final class Value {
private final String mapping, path;
private Value(
Class type,
String mapping,
String path) {
this.mapping = mapping;
this.path = path;
VALUES.get(type).add(this);
}
/* ~~ final class, field getters need not be ~~ */
}
}
Extending it:
public class UserMapping extends ReturnMapping {
public static final Value INDEX, GET_ALL_USERS;
static {
UserMapping factory = new UserMapping();
INDEX = factory.newValue("/users", "index");
GET_ALL_USERS = factory.newValue("/users", "getAllUsers");
}
}
The factory model is nice because it solves two problems:
Instances can only be created from within the extending class.
Anybody can create a new factory but only the class itself can access the newValue method. The constructor for Value is private so new constants can only be created by using this method.
new UserMapping().values() forces the values to be instantiated before returning them.
No more potential errors in this regard. And the ReturnMapping class is empty and instantiating new objects in Java is fast so I wouldn't worry about overhead. You can also easily create a static field for the list or add static methods such as in solution #1 (though this would deflate the design's uniformity).
There are a couple of downsides:
Can't return the subtyped values List.
Now that the constant values are not extended they are all the same class. Can't dip in to generics to return differently-typed Lists.
Can't easily distinguish what subtype a Value is a constant of.
But it's true this could be programmed in. You could add the owning class as a field. Still shaky.
Sum Of It
Bells and whistles can be added to both of these solutions, for example overriding toString so it returns the name of the instance. Java's enum does that for you but one of the first things I personally do is override this behavior so it returns something more meaningful (and formatted).
Both of these designs provide more encapsulation than a regular abstract class and most importantly are far more flexible than Enum. Trying to use Enum for polymorphism is an OOP square peg in a round hole. Less polymorphism is the price to pay for having enumerated types in Java.

Categories

Resources