My question concerns classes design in OOP. Let say we have ItemBase which is parent class for Canceled, Modified and Added class. We also have DueToBase class - parent of Provider and Distributor.
ItemBase may be changed due to DueToBase class.
Assume that ItemBase has property of type DueToBase, and DueToBase has interface method called compute(). Compute algorithm is RELATED to the specific ItemBase derived class. So we have six different possible combinations of ItemBase-DueToBase relationship.
Example.
ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();
My question is how should relationship between ItemBase and DueToBase be built in real object oriented programming ? I do not see swich/case or if condition clause in compute method for checking which type of instance ItemBase is.
It gets even worse if DueToBase has another XXXBase class inside which has another interface method YYY() which algorithm depends on the specific instance of DueToBase (and even on the ItemBase).
How to deal with such cases ? Is there any good programming pattern for such things ? Maybe direction I followed is bad. I would appreciate for your assistance.
maybe that my diagram was not clear. The problem is with following...
pseudocode:
doSomething(){
if(itemBase instanceof Cancelled){
if(dueToBase instanceof Provider)
algorithm1();
else if(dueToBase instanceof Company)
algorithm2();
}else if(itemBase instanceof Modified){
if(dueToBase instanceof Provider)
algorithm3();
else if(dueToBase instanceof Company)
algorithm4();
}else if(itemBase instanceof Added){
if(dueToBase instanceof Provider)
algorithm5();
else if(dueToBase instanceof Company)
algorithm6();
}
}
it gets even worse with deeper if clauses.
Your ItemBase class can be an abstract class with compute() method in it, and all the child classes can have their own implementation.
So later you can do something like this,
ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();
Now, when you will call compute method on ib.changed, it will execute compute implementation of Added class.
In your case, due to base class, Add a instance variable which distinguish between Provider and Company. Something like a boolean flag or int.
Then instead of using dueToBase instanceof Provider you can just create if statement. So your updated pseudo code will decreased to few line. Something like this,
doSomething(){
if(dueToBase.isProvider) {
algorithm1(); //execute if Provider
} else {
algorithm2(); //execute if Company
}
}
Now the complexity to choose compute will be handled by Abstract pattern and then you just have to worry about whether it is company or provider.
the better way will be:
interface Algorithm {
void executeAlgorithm();
}
and have classes, that implement Algorithm interface, instead of functions. Algorithm1, Algorithm2, Algorithm3 and so on.
and have table:
Algorithm[,] algorithmTable = { { new Algorithm1(), new Algorithm2() },
{ new Algorithm3(), new Algorithm4() },
{ new Algorithm5(), new Algorithm6() }
};
and have maps
Map< Class<?> , Integer > itemBaseMap = new HashMap<>();
Map< Class<?> , Integer > dueToBaseMap = new HashMap<>();
and somewhere build this maps
itemBaseMap.add( Canceled.class , 0 );
itemBaseMap.add( Modified.class , 1 );
itemBaseMap.add( Added.class , 2 );
dueToBaseMap.add( Provider.class, 0 );
dueToBaseMap.add( Company.class, 1 );
and in doSomething method you can write
void doSomething( ItemBase itemBase, DueToBase dueToBase ) {
Integer itemBaseIndex = itemBaseMap.get( itemBase.getClass() );
Integer dueToBaseIndex = dueToBaseMap.get( dueToBase.getClass() );
Algorithm algorithm = algorithmTable[ itemBaseIndex, dueToBaseIndex ];
algorithm.executeAlgorithm();
}
I'd say Strategy Pattern
abstract class ItemBase {
public DueToBase myDueToBase;
public void partOfTheAlgorithmThatOnlySpecificIBKnows();
}
class Modified extends ItemBase {
public void partOfTheAlgorithmThatOnlySpecificIBKnows() {
//stuff only Modified knows
}
}
abstract class DueToBase {
public void partOfTheAlgorithmThatOnlySpecificDTBKnows();
}
class Provider extends DueToBase {
//relevant code
public ItemBase myItemBase;
public void partOfTheAlgorithmThatOnlySpecificDTBKnows(){
//stuff only provider knows
}
public void compute() {
//you can also pass this but pointless since you all ready have the reference
myItemBase.partOfTheAlgorithmThatOnlySpecificIBKnows();
//some more code
}
}
ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();
In the example this will call:
1. compute on Provider
2. part of the algorithm that Modified knows how to calculate
3. rest of the code for the algorithm
so at the compute function you have all the specific methods you need for the inherited classes and you can vary the algorithm in the compute() function.
If this doesn't solve your problem you might just have to figure a new design looking at the requirements as Owl said.
Also has no ifs but has more methods in which you are kind of doing the same thing has with the ifs, you are just letting the Inheritance mechanism do it for you.
you can do so:
interface Algorithm {
void executeAlgorithm(DueToBase dueToBase);
}
and have map
Map<Class, Algorithm> algorithmMap = new HashMap<Class, Algorithm>();
you will have classes for each algorithm
for example:
/**
* this class is, for example, when itemBase instanceof Cancelled
*/
class Algorithm1 implements Algorithm {
public void executeAlgorithm(DueToBase dueToBase) {
if ( dueToBase instanceof Provider ) {
someAlgorithm(); // the algorithm specified somewhere, for provider
} else if ( dueToBase instanceof Company ) {
anotherAlgorithm(); // the algorithm or Company.
}
// this someAlgorithm() and anotherAlgorithm() are not same for different Algorithm classes
}
somewhere you must build algorithmMap.
algorithmMap.add( Cancelled.class , new Algorithm1() );
algorithmMap.add( Modified.class , new Algorithm2() );
algorithmMap.add( Added.class , new Algorithm3() );
and in doSomething method you won't have to write if-else blocks
doSomething() {
Algorithm algorithm = algorithmMap.get( itemBase.getClass() );
algorithm.executeAlgorithm(dueToBase);
}
in my opinion this is one of good oop solutions of this problem.
Related
I've been thinking about implementing a certain tactic for my code.
This is my setup:
I've got an interface called "Object".
Then I've got an interface called "Entity" that extends "Object".
From entity then springs countless implementations, like "army", "city", "lemon", etc.
Now, I want to gather all of these Objects into some form of map. Then from that map I want to get the particular implementation of "Object".
My thought out solution for this is as follows:
Object has method :
public Entity getEntity()
All implementations of Object returns null, while Entity returns itself.
Likewise, in entity I'd have:
public Army getArmy()
public City getCity()
That way, I can simply pull an object from the map and get the specific class from it with a series of null checks, like so;
Object o = Objects.getObject(2dCoordinates);
Entity e = o.getEntity();
if (e != null){
Army a = e.getArmy();
if (a != null)
a.armySpecificMethod();
}
All without using "instanceof" and casting, which I hate.
The question is whether there's some unforeseen problem about this? I'd rather learn from someone that knows before refactoring my code and find out for myself.
You asked if there are any pitfalls to your strategy. I would say no, since C# uses the same strategy with their as keyword. Example: e as Army would return e if e is-a Army, or null otherwise. It is basicly a cast that instead of failing returns null.
However you don't have to implement this functionality using interfaces, you can write your own as method for example like this:
static <T> T as(Class<T> clazz, Object obj) {
if (clazz.isInstance(obj)) {
return (T) obj;
}
return null;
}
usage:
Object o = Objects.getObject(2dCoordinates);
Entity e = as(Entity.class, o);
if (e != null) {
Army a = as(Army.class, e);
if (a != null)
a.armySpecificMethod();
}
Another approach would be to register callbacks/strategies to be invoked on particular events. Something like that:
public interface OnMapClicked<T> {
void onItemSelected(T item);
}
And your GameMap (or whatever) implementation would be:
public GameMap {
private final Map<Class<?>, OnMapClicked> listeners = new HashMap<>();
public <T> void registerListener(Class<? extends T> type, OnMapClicked<T> listener) {
listeners.put(type, listener);
}
//
private void onMapClicked(Coordinates coordinates) {
Object object = findObject(coordinates);
listeners.get(object.getClass()).onItemSelected(object);
}
}
That's very rough untested implementation, but hopefully you got the idea. There is one usage of non-generic instance here (in onMapClicked), but it should be safe, since we're checking the input type in registerListener.
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.
I have several child classes that extend a parent class, forced to have a uniform constructor. I have a queue which keeps a list of these classes, which must extend MergeHeuristic. The code that I currently have looks like the following:
Class<? extends MergeHeuristic> heuristicRequest = _heuristicQueue.pop();
MergeHeuristic heuristic = null;
if(heuristicRequest == AdjacentMACs.class)
heuristic = new AdjacentMACs(_parent);
if(heuristicRequest == SimilarInterfaceNames.class)
heuristic = new SimilarInterfaceNames(_parent);
if(heuristicRequest == SameMAC.class)
heuristic = new SameMAC(_parent);
Is there any way to simplify that to dynamically instantiate the class, something along the lines of:
heuristic = new heuristicRequest.somethingSpecial();
That would flatten that block of if statements.
It looks like you're using the class on the queue as a sort of flag to indicate what type of request to instantiate. Another approach that doesn't use reflection is to make this flag behavior explicit by introducing an enum to indicate the request type, with a factory method:
public enum HeuristicType {
AdjacentMACsHeuristic(AdjacentMACs.class) {
#Override public MergeHeuristic newHeuristic(ParentClass parent) {
return new AdjacentMACs(parent);
}
},
SimilarInterfaceNamesHeuristic(SimilarInterfaceNames.class) {
#Override public MergeHeuristic newHeuristic(ParentClass parent) {
return new SimilarInterfaceNames(parent);
}
},
... // other types here.
;
private final Class<? extends MergeHeuristic> heuristicClass;
public Class<? extends MergeHeuristic> getHeuristicClass() {
return heuristicClass;
}
abstract public MergeHeuristic newHeuristic(ParentClass parent);
private HeuristicType(Class<? extends MergeHeuristic> klass) {
this.heuristicClass = klass;
}
}
Your client code then becomes:
Queue<HeuristicType> _heuristicQueue = ...
HeuristicType heuristicRequest = _heuristicQueue.pop();
MergeHeuristic heuristic = heuristicRequest.newHeuristic(_parent);
The main advantages of using an enum as opposed to reflection are:
You're explicitly stating the requirements for adding a new heuristic type, i.e. that there must be a heuristic class and that you must be able to instantiate it based on a parent.
You have a single point in the system where you can see all available heuristic types.
By abstracting the instantiation into a factory method, you allow the possibility of alternate constructor signatures.
You could use reflection, but it won't make the code any prettier.
try {
Constructor<? extends MergeHeuristic> heuristicConstructor =
heuristicRequest.getConstructor(_parent.getClass());
heuristic = heuristicConstructor.newInstance(_parent);
} catch (Exception ex) {
// TODO Handle this
}
Only do this if you're planning on having a lot of different classes. Don't bother if it's only going to be 3 of them, your code is fine for that.
Unfortunately you can't enforce a class to have a certain constructor or a static method - both would be very useful in your case.
As all constructors take the same argument there is one other way to simplify your code using dynamic class instantiation:
Constructor c = heuristicRequest.getConstructor(ParentClass.class).
heuristic = c.newInstance(_parent);
Note that your code did not contain the class type of _parent - in the code sample I named it ParentClass.class - you have to adapt that to your code.
Is Class.forName(heuristicRequest.getName()) an option?
Then constructor heuristicRequestClass.getDeclaredConstructor(_parent.getClass());
Last heuristic = constructor.newInstance(_parent);
At work, we are developing an PHP application that would be later re-programmed into Java. With some basic knowledge of Java, we are trying to design everything to be easily re-written, without any headaches. Interesting problem came out when we tried to implement composite pattern with huge number of methods in leafs.
What are we trying to achieve (not using interfaces, it's just a quick example):
class Composite {
...
}
class LeafOne {
public function Foo( );
public function Moo( );
}
class LeafTwo {
public function Bar( );
public function Baz( );
}
$c = new Composite( Array( new LeafOne( ), new LeafTwo( ) ) );
// will call method Foo in all classes in composite that contain this method
$c->Foo( );
// same with Bar
$c->Bar( );
It seems like pretty much classic Composite pattern, but problem is that we will have quite many leaf classes and each of them might have ~5 methods (of which few might be different than others). One of our solutions, which seems to be the best one so far and might actually work, is using __call magic method to call methods in leafs.
Unfortunately, we don't know if there is an equivalent of it in Java.
So the actual question is: Is there a better solution for this, using code that would be eventually easily re-coded into Java? Or do you recommend any other solution? Perhaps there's some different, better pattern I could use here.
In case there's something unclear, just ask and I'll edit this post.
Edit:
Actual problem is that not every leaf class contains, for example, method Baz. If we used simple foreach to call Baz in every class, it'd give use bunch of errors, as there are certain classes that don't contain this method. Classic solution would be to have every single method from every single leaf class implemented into Composite class, each with different implementation. But this would make our composite class huge and messy with amount of methods we use.
So usual solution would look like this (Composite class):
class Composite implements Fooable, Bazable {
...
public function Foo( ) {
foreach( $this->classes as $class ) {
$class->Foo( );
}
}
public function Baz( ) {
...
}
}
To prevent our code to become real mess, we were thinking about something like:
class Composite {
...
public function __call( ) {
// implementation
}
}
But we aren't really sure if it's a good solution and if there's something similar also in Java (as asked already before edit).
Within Java you could consider using the visitor pattern whereby you pass a visitor object to each node in the tree and the node makes a callback to the visitor class to determine which behaviour should be performed.
This avoids any casting or explicitly checking the type of each node.
/**
* Visitor capable of visiting each node within a document.
* The visitor contains a callback method for each node type
* within the document.
*/
public interface DocumentNodeVisitor {
void visitWord(Word word);
void visitImage(Image img);
}
/**
* Base interface for each node in a document.
*/
public interface DocumentNode {
void applyVisitor(DocumentVisitor v);
}
/**
* Conrete node implementation representing a word.
*/
public class Word implements DocumentNode {
private final String s;
public Word(String s) { this.s = s; }
public String getValue() { return this.s; }
public void applyVisitor(DocumentVisitor v) {
// Make appropriate callback to visitor.
v.visitWord(this);
}
}
/**
* Conrete node implementation representing an image.
*/
public class Image implements DocumentNode {
public void applyVisitor(DocumentVisitor v) {
// Make appropriate callback to visitor.
v.visitImage(this);
}
}
public class Paragraph implements DocumentNode {
private final List<DocumentNode> children;
public Paragraph() {
this.children = new LinkedList<DocumentNode>();
}
public void addChild(DocumentNode child) {
// Technically a Paragraph should not contain other Paragraphs but
// we allow it for this simple example.
this.children.add(child);
}
// Unlike leaf nodes a Paragraph doesn't callback to
// the visitor but rather passes the visitor to each
// child node.
public void applyVisitor(DocumentVisitor v) {
for (DocumentNode child : children) {
child.applyVisitor(v);
}
}
}
/**
* Concrete DocumentVisitor responsible for spell-checking.
*/
public class SpellChecker implements DocumentVisitor
public void visitImage(Image i) {
// Do nothing, as obviously we can't spellcheck an image.
}
public void visitWord(Word word) {
if (!dictionary.contains(word.getValue()) {
// TODO: Raise warning.
}
}
}
Visitor design pattern is a quite good solution. But you have to consider possible changes in the structure, e.g. new Leaf class will make you implement applyVisitor and add visit* method to every other Visitor you have created. So Visitor really helpts you to add behaviour to structured objects at price of that structure not changing too often. If the structure changes often and the algorithms not so much, you might consider having different composites for objects with same interfaces. If you want to do it the dirty way as you currently do in PHP, look at Java reflection API. Nice solution would be imho dynamic calls (as in Ruby or Python). You can simulate those, but that would be much work... So my answer is use the Visitor with care or consider different Composites for objects with different behaviour.
I am trying to write a Factory Pattern to create either a MainMode or a TestMode in my program. The code I was previously using to create these objects was:
play = (isMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, randNo());
My Game (play) would either create a MainMode object or a TestMode object depending on a boolean value (isMode). As you can see I am adding an extra value into my TestMode object (randNo()). This value is used within TestMode to allow the user to input their own "Random Number", whereas within the MainMode constructor this was randomly generated. In this program both MainMode and TestMode are sub-classes of the abstract class Game.
Now I want to replace this line with a Factory Pattern, although I am unsure as my TestMode constructor requires an extra object and I am unsure where I would need to pass this value. If I were going to create a Factory it'd need to be in a new class, probably named GameFactory or ModeFactory or something along those lines.
How would I go about this?
EDIT: The problem here is that the code above is in my GUI, where the values for numberRanges, numberOfGuesses and the randNo() method are. I want to create a Factory class but I am unable to pass these values through because randNo() activates itself. Here is my randNo() method.
private int randNo() {
boolean isValidNumber = true;
int testRandomNum = 0;
while(isValidNumber) {
try {
testRandomNum = Integer.parseInt(JOptionPane.showInputDialog("Enter Random Number"));
isValidNumber = false;
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Sorry, but the number you entered was invalid");
}
}
return testRandomNum;
}
The problem is that whenever I pass randNo() it displays the JOptionPane. As I've said already the GUI and Logic is separate. The GUI is in a GUI package whilst the rest of the code is in the logic package.
Note that some of the other answers may arguably describe factories, but don't describe the GOF Factory Pattern.
Now I want to replace this line with a
Factory Pattern, although I am unsure
as my TestMode constructor requires an
extra object and I am unsure where I
would need to pass this value.
Well, you could think of it this way: MainMode, not TestMode, is the one that does a special thing. The special thing it does, is to ignore the given number, in order to ensure it's really random. In this way of thinking about it, it's MainMode that does something extra.
Or, if other than the randomness, MainMode and TestMode are not different, then you'd be thinking perhaps that you can factor out that similarity into one class, which is provided one of two Strategies for calculating random numbers. One Strategy would actually be random, and one would be perverse, with a random range of only 1 value.
But let's assume that there are other differences between MainMode and TestMode -- presumably TestMode outputs extra debugging to System.out or something.
We can still factor out "how do we supply randomness" from are we testing or playing the game for real". These are orthogonal concerns.
So now we know that in addition to whatever else a 'Mode does, it should accept a Randomness Strategy. Then we could, for example, when you're told that the standard platform random isn't really random enough, you can replace it with a better random.
Or you can do testing where the range of randoms is constrained to only two choices, or always alternates from one to zero, or returns on each call the next value in some Vecrtor or Iterator.
So we use the GOF Strategy Pattern to build the randomness strategies:
interface RandomStrategy {
public double random();
}
public class NotSoRandom implements RandomStrategy {
private double r;
public NotSoRandom( final double r ) { this.r = r; }
public double random() { return r; }
}
public class PlatformRandom implements RandomStrategy {
public double random() { return Math.random(); }
}
Now, if your whole app only ever creates one 'Mode, there's no need for a factory; you use a factory when you need to create the same class type over and over; the Factory is in fact just a Strategy for creating the right kind of (sub) class.
In production code, I've used factories where I have some generic class that creates stuff, and I need to tell how to create the right subclass to create; I pass in a factory to do that.
Now we create a Factory pattern for the 'Mode; this will be surprisingly similar to the Strategy pattern:
abstract class Mode() {
private RandomStrategy r;
public Mode( final RandomStrategy r ) { this.r = r; }
// ... all the methods a Mode has
}
public class MainMode implements Mode {
public MainMode( final RandomStrategy r ) { super(r); }
}
public class TestMode implements Mode {
public TestMode( final RandomStrategy r ) { super(r); }
}
interface ModeFactory{
public Mode createMode( final RandomStrategy r );
}
public class MainFactory() {
public Mode createMode( final RandomStrategy r ) {
return new MainMode(r);
}
}
public class TestFactory() {
public Mode createMode( final RandomStrategy r ) {
return new TestMode(r);
}
}
So now you know about the Factory Pattern and Strategy Pattern, and how they're similar in "shape", but different in how they're used: Factory Pattern is Object Creational and returns an object to be used; Strategy is Object Behavioral, and an instance is usually created explicitly and a reference is held to the instance, to encapsulate an algorithm. But in terms of the structure, they're quite similar.
Edit: the OP asks, in a comment, "How would I integrate this into my GUI?"
Well, none of this belongs in the GUI of your program, except possibly the 'Mode. You'd create the ConcreteStrategy and pass it to the preferred Factory in some setup routine, possibly determining which to use based on command line arguments or config files. basically, you'd select the correct factory very much as you selecting the correct class in your original post. Again, if you're only ever creating one of something, you don't need a Factory; factories are for mass production (or creating families of related concrete types -- though that's beyond the scope of this question).
(Assume we have a game where the user can select on the command line whether to fight robots or dragons; then we'd want to instantiate an OpponentFactory that produce Opponents (an interface), with derived classes RobotOpponent and DragonOpponent, and pass that factory to the part of the game that spawnsNewOpponent(). Similarly, a user might select brave or cowardly opponents, which we'd set up as a Strategy. We don't need to make more Strategy instances, as a Strategy is usually idempotent (stateless and singleton).)
static int main( String[] args ) {
// setup game world
final RandomStrategy r = "random".equals(args[0])
? new PlatformRandom() : new NotSoRandom( Integer.intValue(args[0]) ) ;
// notice the simlarity to the code you originally posted;
// we factored out how to achieve "randomness" as a Strategy.
// now we will use our Strategy to setup our Factory;
final ModeFactory f = "test".equals(args[1])
? new TestFactory(r) : new MainFactory(r);
// also similar to your code
// we've just added an extra level of indirection:
// instead of creating a Mode, we've created an object that can create Modes
// of the right derived type, on demand.
// call something that uses our factory
functionThatRunsameAndNeedstoProduceModesWhenevertNeedsTo( f );
}
The whole point of a Factory is that it should have the needed state to create your Game appropriately.
So I would build a factory like this:
public class GameFactory {
private boolean testMode;
public GameFactory(boolean testMode) {
this.testMode = testMode;
}
public Game getGame(int numberRanges, int numberOfGuesses) {
return (testMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, getRandom());
}
private int getRandom() {
. . . // GUI code here
}
}
Now you can initialize this factory somwhere in your app, and pass it in to whatever code needs to create a Game. This code now doesn't need to worry about what mode it is, and passing extra random params - it uses a well known interface to create Games. All the needed state is internalized by the GameFactory object.
Try somthing like,
abstract class ModeFactory {
public static Mode getMode(isMode, numberRanges, numberofGuesses) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, randNo());
}
public static Mode getMode(isMode, numberRanges, numberofGuesses, someNumber) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, someNumber);
}
}
The class is abstract just to stop intialization. You could modify it to use final and then create a private constructor.
Your code could probably be changed into a factory pattern.
Something like:
public static Mode createMode(boolean isMainMode)
{
if(isMainMode) return new MainMode(...);
return new TestMode(...);
}
Place this method somewhere sensible (this one is tricky, maybe a static ModeFactory)
This assumes that MainMode and TestMode are subtypes of the same type (subclasses or implement Mode interface)
Now all play has to do is call ModeFactory.createMode(...) and pass the appropriate boolean.
Edit (in response to OP update):
Your rand() gets evaluated before the actual constructor is called, and it presents the GUI. Is that what you mean by activating itself?
You have to make the design decision where you want to make the decision about the mode. If you have a GUI and you have a model, it might be preferable to design the GUI to know whether or not the call to random generation (and popup) is necessary before you call the factory method, and then pass the random number to the factory method and let it just pick the correct constructor.
Having it the other way around (model calls your GUI) is trickier and probably a bad idea.
interface ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses);
}
class MainModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new MainMode(numberRanges, numberOfGuesses);
}
}
class TestModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new TestMode(numberRanges, numberOfGuesses, randNo());
}
}
...
play = modeFactory.createMode(numberRanges, numberOfGuesses);
So at startup you create the appropriate mode factory, passing it in to wherever the play needs to be created.
Very simply, ALWAYS USE A PARAMETER, in case the parameter is not used, send null, if you have several parameters for other "Modes", encapsulate them, into a single parameter.
If you are just after factory method, that will create for you a class of a given name try this:
public static MyInterface createClass(String name) throws IllegalAccessException,
InstantiationException, ClassNotFoundException {
try {
Class myClass = Class.forName(name);
MyInterface myObj = (MyInterface) myObj.newInstance();
return myObj;
} catch (ClassNotFoundException ex) {
logger.error("Could not find a class {}", name);
throw ex;
} catch (InstantiationException e) {
logger.error("Class must be concrete {}", name);
throw e;
} catch (IllegalAccessException e) {
logger.error("Class must have a no-arg constructor {}", name);
throw e;
}
}
What you realy want to do, is make a factory, which returns you an object of abstract class or interface (theyr implementors of course). In the factory method you then deside, which implementor to choose. You if you choose an abstract class, you can implement some common logic in it and let other methods unimplemented (declaring them abstract). You would let the concrete descenders implement them depending on theyr need. This is factory design pattern:
public class GridManagerFactory {
public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
AbstractGridManager manager = null;
// input from the command line
if(args.length == 2){
CommandLineGridManager clManager = new CommandLineGridManager();
clManager.setWidth(Integer.parseInt(args[0]));
clManager.setHeight(Integer.parseInt(args[1]));
// possibly more configuration logic
...
manager = clManager;
}
// input from the file
else if(args.length == 1){
FileInputGridManager fiManager = new FileInputGridManager();
fiManager.setFilePath(args[0]);
// possibly more method calls from abstract class
...
manager = fiManager ;
}
//... more possible concrete implementors
else{
manager = new CommandLineGridManager();
}
manager.setLifecicleAlgorithm(lifecicleAlgorithm);
return manager;
}
}
The commoun logic in the abstract class is available to its descenders:
public abstract class AbstractGridManager {
private LifecicleAlgorithmIntrface lifecicleAlgorithm;
// ... more private fields
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
//Methods common to all implementors
public Grid calculateNextLifecicle(Grid grid){
return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
}
public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
return lifecicleAlgorithm;
}
public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
this.lifecicleAlgorithm = lifecicleAlgorithm;
}
// ... more common logic and geter-seter pairs
}
The concrete implementor only need implement the method which is declared abstract:
public class FileInputGridManager extends AbstractGridManager {
private String filePath;
#Override
public Grid initGrid() {
return this.initGrid(this.getFilePath());
}
public Grid initGrid(String filePath) {
List<Cell> cells = new ArrayList<>();
char[] chars;
File file = new File(filePath); // for ex foo.txt
// ... more logic
return grid;
}
}
The receiver of AbstractGridManager would call the methods on him and get the logic, implemented in the concrete descenders (and partually in the abstract class methods) without knowing what is the concrete implementation he got. This is also know like inversion of control or dependency injection