I have a simple Factory (GenericFudge) that creates objects of different types depending on external circumstances. Currently, my code looks something like this:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
#Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
#Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
My goal is to get the details of chocolate and vanilla out of GenericFudge, so that when CaramelFudge is implemented, no changes to GenericFudge are required. For example, GenericFudge would iteratively call a "createIfItsMyFlavor()" method for every xxxFudge class. (In my actual application, I have to try them iteratively, but I'd be interested in other possibilities.)
My instinct was to use a static initializer per subclass (per xxxFudge) that adds "itself" to a list by calling a registerFudge method of GenericFudge, but this hits the chicken-and-egg problem (the class is never used, so its static initializer never gets invoked).
No doubt there's a better way I haven't envisioned. Thanks!
If you are using any kind of dependency injection system like Spring, this is easy to implement using #PostConstruct. If this works, then you can call a register method in GenericFudge from the method you annotate with PostConstruct. In GenericFudge, you have a map, and whenever addType is called you add it to the map. That way your GenericFudge remains unchanged, and new callers will register using PostConstruct. To simplify things further, you can define this in your base class Fudge, and pass the fudge name using the constructor, that way you don't have to declare the register method in each sub-class.
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
#Autowired
private GenericFudge fudge;
#PostConstruct
private void register() {
fudge.addType(fudge, this);
}
In GenericFudge
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
If you do not use any dependency injection system:
Another approach could be to have a static method in the base class Fudge, where you declare all the types of fudge and then return an instance based on the request. That way you don't modify the GenericFudge class, but only the base class of Fudge. This is not ideal, but it gets you away from having to modify the GenericFudge class, and instead of "registering" with something like PostConstruct, you put an entry into the Map.
Example (ImmutableMap from Guava, you can declare the map however you like , this is only for the example):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}
Related
Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.
In my understanding of Java, the most common ways to set the instance variables of a class object are:
foo.setFooStuff(bar); // put a setter method inside the class
foo = modifyFooStuff(foo, bar); // pass & return entire object
Let's say my main() has an object of class bigA, which contains a collection of class littleA objects (which contain instance variables), and another object of class bigB, which contains a collection of class littleB objects (which have different instance variables from littleA). How do I write a method to modify instance variables of one or more littleA and littleB objects at the same time?
(Note: I suspect this is a common question, but I searched and didn't find it. Maybe I'm using the wrong terminology.)
Edit: more concrete example: Let's say I'm making Monopoly. A player has money (in various denominations) and properties (some with houses). She wants to upgrade some properties to hotels. Money has to be added and subtracted, as do houses and hotels. I know how to do this in a pass-by-reference language, but not using pass-by-value, unless I make the entire game state into one huge object and pass it around, which seems like a lot of memory shuffling and basically the same as using global variables, which is bad, right?
If I understand your question correctly, you write a method on the bigA/bigB classes that take the value you want to set and then walk the collection of littleA/B objects setting the instance variables as you go. Like:
// Assuming Foo has a member collection of smallFoo
Foo A = new Foo();
// do stuff that populates the collection of smallFoo in A
A.setSmallFooZipCode("23444");
public void setSmallFooZipCode(String zip_ {
// for thisSmallFoo in smallFoo
thisSmallFoo.setZip(zip);
// end for
)
Objects (including your container objects) should represent something--thinking of them in terms of A/B makes this a little tough.
On top of that, if you are always modifying an attribute in two classes at once I'd suggest that's a pretty bad code smell...
Off the top of my head I can't think of anything I'd model this way, so it's hard to come up with an example. Either A and B should be contained in a parent ab class (and that class should have the attribute), or a and b should be the same interface--in either case these would then go into a single collection in a parent container.
So that said, you should have a method on the parent container object that does the work. In most cases it shouldn't be a method like "setAttribute...", it should be a method like "doAction". In other words, if your container is a "Herd" and it contains a bunch of Elephants, then you would tell the Herd to move to a certain location and let the Herd object send a message to each elephant telling it where to go.
If you think of methods in terms of "Asking an object to do something for you" rather than operating on an object, it helps make some of these decisions much easier.
You would simply encapsulate BigA and BigB in another object:
class BigWrapper {
private BigA bigA;
private BigB bigB;
public void someMethod() {
bigA.someMethod();
bigB.someMethod();
}
}
someMethod() within BigA would modify the LittleA instances. Same for BigB:
class BigB {
private LittleA[] littles;
public void someMethod() {
//do something with the littles
}
}
Of course, this solution doesn't allow you to specify which Little instances to target, as well as doesn't allow you to specify which behavior should be performed (which specific method to invoke via the littles).
If you want that flexibility, use callbacks:
interface Little { }
class LittleA implements Little { }
class LittleB implements Little { }
interface Callback<T extends Little> {
void perform(int currentIndex, T currentLittle);
}
class CallbackHandler<T extends Little> {
private int[] indexes;
private Callback<T> callback;
public CallbackHandler(int[] indexes, Callback<T> callback) {
this.indexes = indexes;
this.callback = callback;
}
public void perform(T[] littles) {
for(int i = 0; i < indexes.length; i++) {
int index = indexes[i];
callback.perform(i, littles[index]);
}
}
}
class BigWrapper {
private BigA bigA;
private BigB bigB;
public BigWrapper(BigA bigA, BigB bigB) {
this.bigA = bigA;
this.bigB = bigB;
}
public void perform(CallbackHandler<LittleA> aCallback, CallbackHandler<LittleB> bCallback) {
bigA.perform(aCallback);
bigB.perform(bCallback);
}
}
class BigA {
private LittleA[] littles;
public BigA(LittleA[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleA> callback) {
callback.perform(littles);
}
}
class BigB {
private LittleB[] littles;
public BigB(LittleB[] littles) {
this.littles = littles;
}
public void perform(CallbackHandler<LittleB> callback) {
callback.perform(littles);
}
}
The CallbackHandler maps the actual callback to the indexes you want to target.
So you would first create the callback:
Callback<LittleA> aCallback = (currentIndex, currentLittle) -> {
//do what you want to the littles
};
Then pass that to a CallbackHandler, which allows you to specify the indexes you wish to target:
int[] indexes = { 0, 1, 2 };
CallbackHandler<LittleA> aCallbackHandler = new CallbackHandler<>(indexes, aCallback);
BigWrapper exposes a perform(CallbackHandler<LittleA>, CallbackHandler<LittleB>), so you would pass the handlers to that method.
An MCVE would look like:
public static void main(String[] args) {
LittleA[] littleA = {
new LittleA(),
new LittleA(),
new LittleA()
};
LittleB[] littleB = {
new LittleB(),
new LittleB(),
new LittleB()
};
BigA bigA = new BigA(littleA);
BigB bigB = new BigB(littleB);
BigWrapper big = new BigWrapper(bigA, bigB);
Callback<LittleA> aCallback = (index, little) -> {
//...
};
Callback<LittleB> bCallback = (index, little) -> {
//...
};
CallbackHandler aCallbackHandler = new CallbackHandler(new int[] { 2, 3, 4 }, aCallback);
CallbackHandler bCallbackHandler = new CallbackHandler(new int[] { 5, 6, 7 }, bCallback);
big.perform(aCallbackHandler, bCallbackHandler);
}
I have an interface and its 2 implementations say :
public interface ObjectProcessor {
public void process(List<String> objectNames);
}
public CarImpl implements ObjectProcessor {
#override
public void process(List<String> carNames){
//car logic
} }
public VanImpl implements ObjectProcessor {
#override
public void process(List<String> vanNames){
//van logic
}
}
Now the caller who uses this interface looks like :
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = null ;
if (VehicleType == VehicleType.CAR) {
processor = new CarImpl();
processor.process(vehicleNames);
}
}
VehicleType being an ENUM
This works fine. But is there anyway I can call an interface dynamically without
adding if statements. In the future if I am supporting another vehicle , I need to add an if statement along with a new implementation for the interface . How can I avoid this?
Overwrite abstract factory method in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new CarImpl();
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new VanImpl();
}
};
public abstract ObjectProcessor createImpl();
}
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = vehicleType.createImpl();
processor.process(vehicleNames);
}
VechicleType combines enumeration with factory.
Or you can wirte all logics in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// car logic
}
};
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// van logic
}
};
}
};
public abstract ObjectProcessor createImpl();
}
In this case you don't need implementation classes (CarImpl, VanImpl, ...) any more.
Use Factory pattern. Here are some benefit from using it: http://javarevisited.blogspot.com/2011/12/factory-design-pattern-java-example.html#ixzz3ueUdV947
1) Factory method design pattern decouples the calling class from the target class, which result in less coupled and highly cohesive code?
2) Factory pattern in Java enables the subclasses to provide extended version of an object, because creating an object inside factory is more flexible than creating an object directly in the client. Since client is working on interface level any time you can enhance the implementation and return from Factory.
3) Another benefit of using Factory design pattern in Java is that it encourages consistency in Code since every time object is created using Factory rather than using different constructor at different client side.
4) Code written using Factory design pattern in Java is also easy to debug and troubleshoot because you have a centralized method for object creation and every client is getting object from same place
What you're basically implementing is a Factory pattern like proposed in the other answers. But in the end you will have to write an 'if' or 'switch' statement to select to correct implementation (or strategy) for your enum value. But like you mentioned yourself you'd have to extend this selection pattern whenever you add or remove an enum value. You can circumvent this by using a map like so:
public class ProcessorSelector {
private final Map<VehicleType, ObjectProcessor> processors;
public ProcessorSelector(Map<VehicleType, ObjectProcessor> processors) {
this.processors = processors;
}
public void process(VehicleType type, List<String> input) {
processors.get(type).process(input);
}
}
You can than configure your ProcessorSelector by passing a map with all the processor implementations mapped to the correct enum value (notice I used guava's ImmutableMap to conveniently construct the hashmap:
new ProcessorSelector(ImmutableMap.of(
VehicleType.CAR, new CarImpl(),
VehicleType.VAN, new VanImpl());
You'll never have to change your ProcessorSelector again, only the construction/configuration of the class. In fact you could say we just implemented the strategy pattern here. These selector classes are very common and if you feel you are implementing them quite often you could even use a more generic implementation, I recently described this in a blogpost: https://hansnuttin.wordpress.com/2015/12/03/functionselector/
I'd like to ask for help and some suggestion how to refactor source code which I receive.
Here is pseudocode of my method:
public void generalMethod(String type) {
InputParameters params = new InputParameters();
if (type.equals("someKey1"){
decodeSomeKey1(params);
} else if (type.equals("someKey2"){
decodeSomeKey2(params);
} else if (type.equals("someKey3"){
decodeSomeKey3(params);
} else if (type.equals("someKey4"){
etc...
}
}
}
All methods have the same input parameters. In first step I created new interface and created for each method separate class which implements created interface.
interface ISomeInterfaceDecoder {
void decode(InputParameters params);
}
class DecodeSomeKey1 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
class DecodeSomeKey2 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
Then I created factory class as follows:
class Factory {
ISomeInterfaceDecoder getDecoder(String type) {
if (type.equals("someKey1"){
return new DecodeSomeKey1();
} else if (type.equals("someKey2"){
return new DecodeSomeKey2();
} else if (type.equals("someKey3"){
return new DecodeSomeKey3());
} else if (type.equals("someKey3"){
etc...
}
}
}
}
After these changes the code looks like this:
class SomeClass {
Factory factory = new Factory();
public void generalMethod(String type) {
InputParameters params = new InputParameters();
ISomeInterfaceDecoder decoder = factory.getDecoder(type);
decoder.decode(params);
}
}
Code of this method looks better but...
This method is called very very often. Each time a new instance of the given class is created. This can cause performance problems. So, I think it's not good approach to this problem.
Can you give me some suggestion how I should to refactor this code?
Thanks in advance for help.
Instead of having a key as a String, make it an enum. Then in the enum you can implement the decode() method like this:
public enum MyKeyEnum {
VALUE1 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE1
}
},
VALUE2 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE2
}
}
...
;
public abstract void decode(InputParameters ip);
}
Now in the calling code you can do something like this:
public void generalMethod(MyKeyEnum type) {
InputParameters params = new InputParameters();
type.decode(params);
}
The advantage is that all the decode methods are in 1 enum, you dont need a specific class for each of the decoders. Also when a new value is added to the enum, you cannot forget to implement the decode method (or it will not compile).
Can you give me some suggestion how I should to refactor this code?
I see no mention of automated regression testing, and that would be my first step, to put in a test suite (via, say, JUnit or TestNG) before going further.
After that, I'd perhaps introduce a Map of String keys to Decoder objects.
But put the test framework in first. Otherwise you'll never really know if you've introduced bugs or different modes of operation.
Introduce caching/singletons in your factory, that you only return an algorithm once. Also, make your factory a singleton.
Create a static Map<String, ISomeInterfaceDecoder> where you map the identifier to algorithms executing the call which means no factory class and no algorithm instantiation. Works only, if you have stateless algorithms.
I have Foo.java, which is interface.
And lots of classes that implement it. Bar1.java , Bar2.java etc.
I have a method in frontend, that is like this: getBar(String bar)
I could just do it like this:
if(bar.equals("Bar1")) {
return new Bar1();
}
But can I somehow do it, that everytimes something new implements Foo.java , then I don't have to update my method, with new ELSE statement.
I thought like each implementation have unique ID or something, which I add to BarX.java , whenever I create it.
Any suggestions or thoughts? I thought maybe I can use enum or smthing or any other solution.
FYI: You realize, of course, that you should not write this:
if(bar == "Bar1") {
return new Bar1();
}
You should do it this way:
if("Bar1".equals(bar)) {
return new Bar1();
}
Looks like you need a factory (aka virtual constructor). If all your Foo implementers have a default constructor, you can do this:
public class FooFactory {
public static Foo create(Class<Foo> clazz) {
return clazz.newInstance();
}
public static Foo create(String className) {
return create(Class.forName(className));
}
}
There are exceptions to be handled; I don't have time to spell them out for you. You should see the idea. All you need to do is write a new class and your factory can handle it.
If there are other constructors, just elaborate the theme with parameters and additional calls. This should get you started.
Sounds to me like a job for dependency injection or reflection.
You can do :
Class myClass = Class.forName("my.namespace.MyClass");
That would be with reflection. Not very nice but doing the job.
You can create object by class name:
Class<?> clazz = Class.forName(className);
Object object = ctor.newInstance();
Or if you need call particular constructor (with one String argument strArgument for example):
Constructor<?> c = clazz.getConstructor(String.class);
Object object = c.newInstance(new Object[] { strArgument });
- Reflection is the way to go...
- But still you can use a method like this
public static Foo createObj(Class<Foo> clazz) {
return clazz.newInstance();
}
- And yes to mention, that it should be equals() and not ==
if(bar.equals("Bar1")) {
return new Bar1();
}
This is a classic factory pattern issue.
The solution is whenever you have to maintain a static Map and whenever you have a new "Bar" type you need to registed it in the map first, so whenever you want an object of that type, you can simply pick it from the map.
Consider the below classes
interface IVehicle {
public void drive();
public void stop();
}
class Car implements IVehicle {
public void drive(){
//logic goes here
}
public void stop(){
//logic goes here
}
}
class VehicleFactory{
public IVehicle createVehicle(String VehicleType){
IVehicle vehicle = null;
if("Car".equalsIgnoreCase(VehicleType) ){
vehicle = new Car();
}
if("Bus".equalsIgnoreCase(VehicleType) ){
//vehicle = new Bus();
}
if("Train".equalsIgnoreCase(VehicleType) ){
//vehicle = new Train();
}
return vehicle;
}
}
so whenever you have a new type of vehicle, you have to change the metho by adding the code for new Type of vehicle.
The solution is to improve the VehicleFactory class as below and all vehicle types should register in the map as shown below.
class Car implements IVehicle {
static{
VehicleFactoryFlexible.registerVehicle("Car", new Car());
}
public void drive(){
//logic goes here
}
public void stop(){
//logic goes here
}
public IVehicle createVehicle(){
return (IVehicle) new Car();
}
}
public class VehicleFactoryFlexible {
static Map vehicleRegistry = new HashMap();
public static void registerVehicle(String vehicleType, IVehicle veh){
vehicleRegistry.put(vehicleType, veh);
}
public IVehicle createVehicle(String vehicleType){
IVehicle vehicle = (IVehicle)vehicleRegistry.get(vehicleType);
return vehicle.createVehicle();
}
}
Using reflection you can scan a whole package for all of your BarX classes and work with this list instanciating if your input exists in the list. Or you could just use a Class.forName solution catching directly the error.
EDIT: check this out http://code.google.com/p/reflections/