I have the following Strategy Pattern implemented:
public abstract class RetrievalStrategy {
public abstract List<MyObject> retrieve();
}
public class LimitRetrievalStrategy extends RetrievalStrategy {
public int limit;
public LimitRetrievalStrategy(int limit) {
this.limit = limit;
}
public List<MyObject> retrieve() {
// fill up the list and return it, limiting to 'limit' results
return new ArrayList<MyObject>(limit);
}
}
public class SpeedRetrievalStrategy extends RetrievalStrategy {
public int speed;
public SpeedRetrievalStrategy(int speed) {
this.speed = speed;
}
public List<MyObject> retrieve() {
// do something with the speed and return list again
return new ArrayList<MyObject>();
}
}
My client application receives either a speed or a limit (and perhaps other parameters) from the user. I want to create a factory class that will return the proper strategy based on parameters that have a value and parameters that don't. I don't want the client the decide which Strategy should be returned. Should the factory createStrategy(params) method then have if statements for each parameter and depending on the different combinations (imagine there are other Strategy classes) return the Concrete Strategy class?
What is the proper way to do this?
Oh, RetrievalStrategyFactory, where to begin? This sounds like overengineering for a YAGNI. One approach is create an enum for specifying the "set" field, assuming there's one retrieval strategy per parameter, and use that as the factory.
public enum FieldParameter {
LIMIT {
RetrievalStrategy getRetrivalStrategy(int value) {
return new LimitRetrievalStrategy(value);
}
},
SPEED {
RetrievalStrategy getRetrivalStrategy(int value) {
return new SpeedRetrievalStrategy(value);
}
};
abstract RetrievalStrategy getRetrivalStrategy(int value);
}
Then the client code is not explicitly specifying the retrieval strategy, but it is implicitly given when the client code informs your code which field the user provided.
No, the return value in the method signature should be the common interface or base class.
The factory must have the if tests to decide on the concrete type to return, but that's unavoidable, unless you can craft a Map that returns a concrete instance based on a composite key class that encapsulates parameter combinations.
If you need the ability to extend a factory it you want an Abstract Factory. This is a factory of Factories. An Abstract Factory can have many plugin factories, which can follow a strategy to determine which factory is used.
This is usually needlessly complicated and something you can add later, so its not something you need to do just in case you might need it.
Related
I am trying to make an enum list, and have an abstract method defined in the enum, which each enum value implements. The problem I am facing is that the abstract class has a generic return type but I want each enum value to return a concrete type.
I'll give an example:
public enum Attributes {
name {
#Override
public void createAttribute(Person person) {
//Do some validations
//Save in some storage
}
#Override
public Name getAttribute(Person person) {
// Validations
// Retreive from storage
return new Name("test");
}
},
address {
#Override
public void createAttribute(Person person) {
//Do some validations
//Save in some storage
}
#Override
public Address getAttribute(Person person) {
// Validations
// Retreive from storage
return new Name("test");
}
}
public abstract Object getAttribute(Person person);
public abstract void createAttribute(Person person);
}
Here the issue is that I would need to do typecasting to get the concrete object which is not recommended and I don't get any type of safety. How Should I go about so that using the enum value I can get my concrete object instead of the generic one.
Now I wanna call this as,
Arrays.stream(Attributes.values()).forEach(r -> {
r.createAttribute(person);
}
final Address address = Attributes.address.getAttribute(person);
final Name name = Attributes.name.getAttribute(person);
So now whenever I need to add a new attribute I don't want to write create methods for it in the Person class every time. I just add it to enum and it gets created. But now since I have the create method in the enum, I also want the getAttribute to be present here.
Here the issue is that I would need to do typecasting to get the concrete object which is not recommended and I don't get any type of safety.
You're right. Given an enum type E with an associated enum constant C, the type of the expression E.C is E. Java provides no mechanism for naming or representing a narrower type for that expression. One of the implications is that although an enum instance can implement methods with covariant return types, the covariance is not visible outside the instance. If you depend for some purpose on the narrower return type of one of those instances' methods, then casting is your only alternative.
And you're right that such casts are not type safe. They cannot be checked by the compiler, and in practice, you as programmer can get them wrong. But the information to perform a compile-time check is not expressed by the language, so there is no scope for a workaround in the language as it is defined today.
How Should I go about so that using the enum value I can get my concrete object instead of the generic one.
You should choose an altogether different approach, not involving an enum.
If you stuck with the enum then you would have to adopt an approach that relies on the enum instances to perform any tasks that depend on their own particular characteristics. Because you ask so persistently, one possibility would be to implement a variation on double dispatch. Instead of a getObject() method, you would have something like
void acceptReceiver(AttributeReceiver r, Person p);
paired with
public interface AttributeReceiver {
default void receiveName(Name name) { /* empty */ }
default void receiveAddress(Address addr) { /* empty */ }
}
Of course, the enum instances would have to implement acceptReceiver appropriately.
You would probably want to use that a little more directly than just to retrieve attributes, but you could use it to retrieve attributes something like this:
class Example {
Name name;
Address address;
void retrieveAttributes(Person person) {
AttributeReceiver receiver = new AttributeReceiver() {
public void receiveName(Name n) { name = n; }
public void receiveAddress(Address a) { addr = a; }
};
Attributes.name.acceptReceiver(receiver, person);
Attributes.address.acceptReceiver(receiver, person);
}
}
But that's awfully roundabout when you have the alternative of using (just) methods, whether on Person or even on some non-enum utility class. I continue not to see any advantage to involving an enum here. I think your code overall would be more complex and harder to understand and maintain with enums than without.
The root issue is that you are abstracting away details that you actually care about. That's a deep design flaw. You can program your way around it, but it would be better to choose a more appropriate level of abstraction in the first place.
I have the following very simple interface:
public interface IDataSource<T> {
Observable<T> observable();
}
Now I'll be having multiple implementations of it. Each of those implementation may rely on varying parameters (different storage objects: JDBC, Cassandra, Redis...). So for instance I'll have:
public class CassandraDataSource implements IDataSource<MyCassandraObject> {
#Inject
public CassandraDataSource(Keyspace ks) {
// ...
}
}
public class OtherCassandraDataSource implements IDataSource<MyOtherCassandraObject> {
#Inject
public OtherCassandraDataSource(Keyspace ks) {
// ...
}
}
public class JDBCDataSource implements IDataSource<MyJdbcObject> {
#Inject
public JDBCDataSource(Database db) {
// ...
}
}
And so on.
What I would like is to reference each of those with a string so that i can call a factory which would return the appropriate IDataSource. Something that would behave like that:
public class DataSourceFactory {
public static final Map<String, Supplier<IDataSource<?>>> map = new HashMap<>();
#SuppressWarnings("unchecked")
public <T> IDataSource<T> get(String ref) {
return (IDataSource<T>) map.get(ref).get();
}
}
I could be giving N Providersas parameters (or direct field injection) to my factory (N being the number of IDataSource I use) and map strings to those in the constructor or use a switch in the get method but this would become quite a mess once I reach 10 to 20 IDataSource (or more!)
Is there some simpler solution I've been overlooking ?
Thanks
If you have to have a factory, then no—as in this question a manual factory is probably the best you can get.
However, if you bind all of your IDataSource implementations to IDataSource with different binding annotations, then you might be able to skip the factory and simply inject #Source("foo") IDataSource and get back the instance you want. The configuration between String and implementation still has to live somewhere, but you can have it live in a Guice module if you'd like. And, by injecting the Injector and supplying a compatible annotation implementation, you can even write a factory like DataSourceFactory that defers to Guice.
As a side note, beware of your DataSourceFactory; get will have no safe way to supply a value for its type parameter T.
Let's say I'm building an immutable Yahtzee scorecard class:
public final class Scorecard {
private Map<Category, Integer> scorecard = new HashMap<Category, Integer>();
public Scorecard() {
// Instantiates a new empty scorecard
}
private Scorecard(Map<Category, Integer> scorecard) {
this.scorecard = scorecard;
}
public Scorecard withScore(Category category, int[] roll) {
newScorecard = new HashMap<Category, Integer>(scorecard); // Pretend that this is a deep-copy
newScorecard.put(category, calculateScoreFromRoll(roll));
return new Scorecard(newScorecard);
}
public int getScore(Category category) {
return scorecard.get(category);
}
}
Basically I don't want to expose the internals of the class. If I didn't have a private constructor then I would need to use a public constructor with a Map argument just like the private one (and I could essentialy lose the withScore() method too) in order to allow scoring. But is this a valid way of doing factory methods?
A very common, and good pattern is to have all private constructors and public static factory methods:
public class MyClass {
private MyClass() {}
public static MyClass fromA(A foo) {
MyClass o = new MyClass();
o.field = bar; // etc
return o;
}
public static MyClass fromB(B foo) {
MyClass o = new MyClass();
o.field = bar; // etc
return o;
}
}
Note: This allows different factory methods with the same parameter types, which constructors do not allow.
Factory methods are intended to allow you to get an object without specifying the exact type.
For example, from Effective Java, 2nd edition:
The class java.util.EnumSet (Item 32), introduced in release 1.5, has no public constructors, only static factories. They return one of two implementations, depending on the size of the underlying enum type: if it has sixty-four or fewer elements, as most enum types do, the static factories return a RegularEnumSet instance, which is backed by a single long; if the enum type has sixty-five or more elements, the factories return a JumboEnumSet instance, backed by a long array.
The existence of these two implementation classes is invisible to clients. If RegularEnumSet ceased to offer performance advantages for small enum types, it could be eliminated from a future release with no ill effects. Similarly, a future release could add a third or fourth implementation of EnumSet if it proved benefi- cial for performance. Clients neither know nor care about the class of the object they get back from the factory; they care only that it is some subclass of EnumSet.
Using constructors instead of static methods like you suggested breaks the factory method pattern, because by using the constructor directly you are specifying an implementation.
In your case, if you want to use a factory method you would make the default constructor private so clients could not directly instantiate a ScoreCard. At this point, you're free to use whatever specific implementation of ScoreCard in the factory method. For example, if you make a second ScoreCard class that is backed with a TreeMap, you can switch which implementation of ScoreCard that the client gets just by changing the static factory.
I have a code which was initially designed for just a single team where they were passing an enum [which stores list of tasks] to an api. This api then progates the use of this enum to many other classes.
Now i have a task where this code needs to be used by multiple teams and they can pass there own set of tasks in form of enums.
Given the current implementation i dont think it is feasible to support multiple teams which completely overhauling the code because enum's cannot extend other enums.
Is there any way to implement this without massive changes?
But... enums can implement interfaces, for example:
public interface Task {
int getPriority(); // just for example
// plus whatever methods define a task
}
public enum Team1Task implements Task {
Task1(1),
Task2(3);
private final int priority;
private Team1Task(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
}
Now we can employ java generic kung fu to specify a generic parameter bounded to a suitable enum:
public class TaskProcessor<T extends Enum<T> & Task> {
public void process(T task) {
// do something with task
}
}
To use it:
TaskProcessor<Team1Task> p = new TaskProcessor<Team1Task>();
p.process(Team1Task.Open); // will only accept a Team1Task instance
FYI, as a curiosity of generics, you can alternatively use this bound to achieve the same thing:
public class TaskProcessor<T extends Enum<? extends Task>> {
Although I can find no practical difference in effect, I find it lacks the clarity and familiar pattern of the intersection bound above. For more on this see this question.
It is comparatively easy to make much of the work around enums generic.
Here's a severely cut-down example. It defines a generic database Table class that takes an enum Column as its defining type. The enum defines what columns are in the table. The defining type is an enum that also implements an interface which is a really useful trick.
public class Table<Column extends Enum<Column> & Table.Columns> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
You can now create your real table with something like:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
Note that this is a truly trivial example but with a little work it is easy to move a lot of your enum work into the parent class.
This technique does retain the type-safety checks you get when using generics.
Enums can implement interfaces. I would recommend coming up with a reasonable interface for the task. make your enum implement the interface and your code will continue to work just fine. other teams can use whatever interface implementation they desire (their own enum or something else). (note, without code it's hard to make very explicit recommendations).
You probably should not use enums for this, but if you want, you can implement logic in helper class, or set of classes that extend each other, and make enums a thin wrappers saround it:
public enum MyTaskEnum {
A, B, C;
private final TaskEnumHelper helper = new TaskEnumHelper();
public void foo (int x, int y)
{
helper.foo (x, y);
}
}
I have created a BicycleProducer interface which has different implementations: OffroadBicycleProducer, FastBicycleProducer and so on.
Each of these factories requires many parameters in order to produce a bicycle. I want to encapsulate these properties in a class and pass it to the produce method. However, the bicycles requires different properties - some may be the same - and I wonder how to do this properly. In the interface of BicycleProducer I have currently a method named produce which takes a parameter BicycleProducingContext which is a interface with all the common properties. And then you have implementations that implement it and add the necassary properties based on what type of bicycle it is. And then you would need to cast it in the produce method....but I don't know. It seem somewhat dodgy (it might not be) I feel.
Is this is a fine approach or should I do it in another way?
public interface BicycleProducer {
void produce(BicycleProducingContext context);
}
public class OffroadBicycleProducer implements BicycleProducer {
public void produce(BicycleProducingContext context) {
context = (OffroadBicycleProducingContext) context;
}
}
and
public interface BicycleProducingContext {
int numberOfBicycles();
void brand(String brand);
}
public class OffroadBycycleProducingContext implements BicycleProducingContext {
//..
}
I find two things sort of awkward about your proposed design:
To me, it looks like you may not need factories (i.e. your Producer classes) at all. Factories are useful when you need to construct an object whose type is not known at compile time. But since you're thinking of having separate factory classes for each type of bicycle (e.g. OffroadBicycleProducer), I assume you do know what kind of object you want to construct ahead of time.
Using a context class to make parameter passing less ugly is a good idea, but if you start creating separate context classes for each type of bicycle, then you end up in the awkward situation of having to know which context to construct as well as what data it requires -- which, if you have all that, you might as well just skip the intermediate step and construct the Bicycle right away.
If I was right in assuming that you do know what kind of object you need to construct ahead of time, then instead of using factories, I would go either with the builder pattern, or with plain old constructors. The constructor approach might look something like the following:
public abstract class Bicycle {
private int year;
private String color;
public Bicycle(BicycleProducingContext context) {
this.year = context.getYear();
this.color = context.getColor();
}
}
public class OffroadBicycle extends Bicycle {
private String terrainType;
public OffroadBicycle(BicycleProducingContext context) {
super(context);
this.terrainType = context.getTerrainType();
}
}
public class FastBicycle extends Bicycle {
private int maxSpeed;
public FastBicycle(BicycleProducingContext context) {
super(context);
this.maxSpeed = context.getMaxSpeed();
}
}
If you don't know what type of Bicycle you want to construct until runtime, then you can use the above approach with a single factory. For example:
public class BicycleFactory {
public static Bicycle constructBicycle(BicycleProducingContext context) {
if (context.getBicycleType().equals("OffroadBicycle")) {
return new OffroadBicycle(context);
} else if (context.getBicycleType().equals("FastBicycle")) {
return new FastBicycle(context);
} else {
throw new IllegalArgumentException("Encountered unrecognized Bicycle type: " + context.getBicycleType());
}
}
}
I hope I'm not over-simplifying your use-case, but it seems to me like the above should accomplish what you're looking for.