factory pattern dynamic approach - java

I am trying to understand factory pattern.If there are many implementation then my factory pattern will have lot of if else or switch cases. And also every time I introduce a new implementation i should change my factory code
Like in below examples if lets assume dog duck are implementing Pet interface like tomorrow if many animals implement pet interface my factory frows long with lot of if else else if code or switch case. Is there any way to solve this with bringing more dynamic approach?
package com.javapapers.sample.designpattern.factorymethod;
//Factory method pattern implementation that instantiates objects based on logic
public class PetFactory {
public Pet getPet(String petType) {
Pet pet = null;
// based on logic factory instantiates an object
if ("bark".equals(petType))
pet = new Dog();
else if ("quack".equals(petType))
pet = new Duck();
return pet;
}
If the animals grows
if ("bark".equals(petType))
pet = new Dog();
else if ("quack".equals(petType))
pet = new Duck();
else if ("mno".equals(petType))
pet = new MNO();
else if ("jkl".equals(petType))
pet = new JKL();
else if ("ghi".equals(petType))
pet = new GHI();
else if ("def".equals(petType))
pet = new DEF();
......
else if ("abc".equals(petType))
pet = new ABC();
return pet

I think there is a dynamic approach:
In your factory you need a Map<String, Class<? extends Pet>>
In static constructor of every class, which extends Pet, register it with such map.
Than creating a class will be just map.get(pet).newInstance ( you'd have to check for nulls, of course)

The idea behind the factory pattern is to let you dynamically instantiate objects whose types you don't necessarily know about at design time.
Having a big if block defeats that purpose.
The effective way to implement this pattern is to also have a factory for each type, which implements a base factory interface and has the ability to instantiate a new object of that type (by the way, in Java, the built-in Class is an example of such a factory).
Then you register a map of names/ids/etc. to instances of these individual factories at runtime. When it's time to instantiate one of the types, you look up the factory in the map by name and use that to instantiate a new object of that type.
How you register individual factories in the map is totally up in the air. You could register some explicitly, you could scan a configuration file, etc.
Essentially you want to replace your if block with a map that is dynamically created at runtime.
You don't even need to solely use a preregistered "map" - sometimes it may be appropriate to figure out how to create an object with a given name on the fly, or a combination of the two (e.g. Class.forName() searches the class path if it can't find the class already loaded). The point is the translation of the name to the class type can take place without the base factory actually knowing what the class type is.
It's worth noting that Java reflection provides a very workable factory implementation already via Class.forName() and/or Class.newInstance(), so consider using that instead of reinventing the wheel if it makes sense.

use reflection
public Pet getPet(String petType)
{
Pet _pet = (Pet)Class.forName(petType).newInstance();
return _pet;
}
you need to change your arguments from 'bark','quack' to 'Dog' and 'Duck' etc

I've been banging my head a little on this since I had a similar problem, and finally I came with a solution based on Reflections Library (pay attention to the final S in Reflections!)
It can be applied to your problem IF all your pet subclasses have an attribute that can be used to discriminate them, for example
public String petType;
The method of your factory could be the following:
public static Pet getPet(String _petType) {
String packageName = "your.package.with.pet.classes";
Reflections reflections = new Reflections(packageName);
Set<Class<? extends Pet>> allPets = reflections
.getSubTypesOf(Pet.class);
Iterator<Class<? extends Pet>> it = allPets.iterator();
while (it.hasNext()) {
try {
Pet pet = it.next().newInstance();
if (pet.petType.equals(_petType))
return pet;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Pet " + _petType
+ " not yet implemented in package " + packageName);
return null;
}
This method would remain unaffected if new Pets were defined.
Pros:
It doesn't need further modification to Pet subclasses, neither any sort of initialization/registration on a Map structure maintained by the Factory
It's more general than the solution based on Java Reflection API because you can discriminate Pet subclasses upon some attributes instead of the class name
Cons:
It creates local instances of all Pet sub-classes to find the appropriate one. On this side, I'm confident that this approach can be improved.

In Java8, there's a Supplier interface that supports this quite well. Reflections and manual invocations can be avoided and a cleaner approach can be used.
Something like this for Factory:
public class DynamicSupplierTierFactory {
public static final Map<String, Supplier<? extends Tier>> registeredSuppliers = new HashMap<>();
static {
registeredSuppliers.put("blue", new BlueSupplier());
registeredSuppliers.put("silver", new SilverSupplier());
registeredSuppliers.put("golden", new GoldenSupplier());
}
public static void registerSupplier(String type, Supplier<? extends Tier> supplier){
registeredSuppliers.put(type, supplier);
}
public static Tier getTier(String type){
Supplier<? extends Tier> supplier = registeredSuppliers.get(type);
return supplier != null ? supplier.get():null;
}
}
Suppliers will be like:
public class BlueSupplier implements Supplier<Tier> {
#Override
public Tier get() {
return new Blue();
}
}
This can be seen here in more detail: https://medium.com/#mhd.durrah/factory-pattern-the-dynamic-way-with-java-8-3ca5ab48a9cf

Related

Creating child objects on basis created parent object in java

I'm learning java design patterns and I wonder if I can apply some with following problem. I have class Solider and some child classes, for example: General and Sergeant. I'm creating Solider object and in runtime I want to change this object to General or Sergeant object, or create new Sergeant or General object using created earlier Solider object:
Solider s = new Solider(...);
.....
if (generalCondition) {
General g = createGeneralFromSolider(s);
//or better:
//General g = promoteSoliderToGeneral(s);
} else if (sergeantCondition) {
Sergeant sr = createSergeantFromSolider(s);
//or better:
//Sergeant sr = promoteSoliderToSergeant(s);
}
Firstly I decided to create additional constructor in General/Sergeant Class:
Class General extends Solider {
General(Solider s, Map<String, String> generalSpecificParams) {
//first we are going to copy all solider params to general params (bad idea if we have a lot of params)
this.setParamX(s.getParamX());
....
//then we can assign the rest of general-specific params
this.setGeneralSpecificParams(generalSpecificParams);
}
}
and use it in methods createGeneralFromSolider but I'm not sure if it is elegant way. Main disadvantage is that I create new object, so after calling createGeneralFromSolider I have 2 object in memory. I would rather have one object in memory: General/Sergeant promoted from Solider (object General/Sergeant which earlier was the Solider object). I wonder if I can use some design patter to resolve it. I remember that in C++ there has been something like copying constructors which copying all params from one object to another by assigning all params, one after another. In Java I didn't hear about anything similar.
You would probably need to use a Factory pattern for this kind of situation.
For example:
public class SoldierFactory {
//use getSoldier method to get object of type Soldier
public Soldier getSoldier(String soldierType){
if(soldierType == null){
return null;
}
if(soldierType.equals("case1")){
return new General();
} else if(soldierType.equals("case2")){
return new Sergeant();
} else if(.....
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
SoldierFactory soldierFactory = new SoldierFactory();
Soldier s1 = soldierFactory.getsoldier("case1");
}
}
I think its better to not create the Soldier ahead of calling Soldier factory. You're going to change it regardless during run-time right?
First of all, when constructing child classes, use super as the first statement of the constructor like so:
class Soldier {
private String rank; // e.g. Pvt, PFC, etc.
private int yearsOfService;
// ... (Standard constructor)
public Soldier(Soldier s) {
this.rank = s.rank; this.yearsOfService = s.yearsOfService;
}
// ... (Getters and Setters)
}
class Sergeant extends Soldier {
private int subordinates;
public Sergeant(Soldier s) {
super(s)
this.rank = "Sergeant"; // overwrites this Sergeant's rank
this.subordinates = 0;
}
}
You could easily encapsulate this in a promoteSoldierToSergeant method. However, this can lead to telescoping constructors if classes with many attributes are designed naively, or necessitate your map-based workaround. To resolve this, I'm personally a big fan of the Builder pattern, but you can also consider the Factory pattern.
Your question regarding "copying constructors" is perhaps best addressed by reading up on the Clonable interface, but be aware of the differences between shallow and deep copies, and the implications for your classes and data structures.
I think your approach is totally acceptable. If you have an object X, that you want to turn into Y, you can do it in Y constructor, copying all necessary fields.
You could as well use a builder, or static factory methods, but either way you'll have to copy fields, as there's no automatic copy constructor in java (except if you use some dedicated library such as lombok, which can provide full-args constructors from annotations)
You worry about having 2 objects in memory. But if you remove every reference of the original Soldier, the garbage collector will destroy it.
Last thing, as mentionned by #tsolakp , is it a good design to have General inheriting from Soldier? Couldn't it be just a "grade" variable, or something like that, to reflect this state? It's a common mistake to overuse inheritance where composition would be sufficient, and would cause less troubles.
What you want could be achieved using Reflections.
That way you can automatically copy fields from the instance of parent to child class.
Your code would look something like this:
public static void copyObject(Object src, Object dest)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException, SecurityException {
for (Field field : src.getClass().getFields()) {
dest.getClass().getField(field.getName()).set(dest, field.get(src));
}
}
public static General createGeneral (Solider solider, String devision) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
General general = new General();
copyObject(solider, general);
general.setDevision(devision);
return general;
}
The Field import is java.lang.reflect.Field;
========================================================================
Another way would be to use the Apache Bean Utils.
Than, you can use it's cloneBean(Object Bean) method like this:
General general = cloneBean(solider);
to copy the fields from solider to general and after that all the fields that are specific to child class (General).
========================================================================
EDIT: It would also be wise to introduce another child class that would be used for "ordinary" soliders if you intended to use the parent class Solider for "ordinary" soliders (which I suppose you do according to your commented method name promoteSoliderToGeneral(Solider s).
So, for example you would have a parent class called MilitaryMan and 3 child classes that extend it: Solider, General and Sergeant.
This way, you can uniformly handle all of the MilitaryMan. And, you can check if the MilitaryMan is a Solider, General or Sergeant with:
if (militaryMan instanceOf Solider) {
// do solider specific processing
...
} else if (militaryMan instanceof General) {
...
} else if (militaryMan instanceof Sergeant) {
...
}
I think it would be cleaner this way.

I am implementing factory design pattern in java

I am implementing factory design pattern in java where I want to keep one overloaded method in abstract class. Will it violate the factory pattern concept?
Or please suggest whether this is right way to implement Factory design pattern ?
abstract class A{
void meth(int a);
void meth(int a,int b);
}
class Factory{
public static A factoryMethod(int a){
if(a==1){
return new Ob1();
}else{
return new Ob2();
}
}
}
class Ob1 extends A{
void meth(int a){}
void meth(int a,int b){}
}
To implement the Factory Pattern first you need to consider what the Factory will produce. Let's produce Vehicles.
public VehicleFactory {
public Vehicle newVehicle(String type) {
...
}
}
which will produce Vehicles according to the class hierarchy below.
public interface Vehicle {
public List<Door> getDoors();
}
public class Motorcycle implements Vehicle {
public List<Door> getDoors() {
return Collections.<Door>emptyList();
}
}
public class SportsCar implements Vehicle {
public List<Door> getDoors() {
return Collections.<Door>unmodifiableList(Arrays.asList(new Door("driver"), new Door("passenger"));
}
}
public class Hatchback implements Vehicle {
public List<Door> getDoors() {
return Collections.<Door>unmodifiableList(Arrays.asList(new Door("driver"), new Door("passenger"), new Door("back"));
}
}
Then your VehicleFactory method newVehicle(...) might look like
public Vehicle newVehicle(String type) {
if ("motorcycle".equals(type)) { return new Motorcycle(); }
if ("sports car".equals(type)) { return new SportsCar(); }
if ("hatchback".equals(type)) { return new Hatchback(); }
return null;
}
Now the main question is "Why would you want to do this?"
Sometimes you want a nice clean interface for building a lot of
related items. You give the related items an Interface and a Factory
to build them. This allows someone using this part of the software to
simply pull in the Interface class and the ItemFactory. They don't
see the individual details, which simplifies their code.
Since you hid the implementation details of all of the Vehicles in the above code, if you had a programming error (or wanted to add something), you can fix one of the Vehicles (or add a new Vehicle) to the factory and re-release the library (JAR file) containing the VehicleFactory.
You know that other people have been using the VehicleFactory methods, so you don't have to worry about their code breaking at compile time, and unless you were careless, you can also assure that it will work at runtime.
This is not the same as saying that the behavior won't change. The new implementations of Vehicle will be returned back, hopefully with fewer embedded bugs. Also, since they didn't ask for the "new vehicles" you might have added they won't see them, until they call newVehicle("station wagon") or something like that.
Also, you can change how the Vehicles are built up. For example, if you later decide that you don't want a simple "just construct it in one pass" implementation style, you could alter 'newVehicle(...)' like so
public Vehicle newVehicle(String type) {
Chassis chassis;
if ("motorcycle".equals(type)) {
chassis = new TwoWheelChassis();
} else {
chassis = new FourWheelChassis();
}
return new ComponentVehicle(chassis, getDoorCount(type));
}
where ComponentVehicle implements Vehicle and for some reason requires an explicit Chassis object.
--- update seeing the "number of methods" question in the comments ---
A Factory pattern is not really about the number of methods, but about one method having the ability to build an abstract thing out of one or more concrete things.
So in the example above, I could have
public VehicleFactory {
public Vehicle newVehicle(String type) { ... }
public Vehicle newRedVehicle(String type) { ... }
public Vehicle newBlackVehicle(String type) { ... }
}
And they would all be acceptible factory methods with respect to the type of the Vehicle, but they would not be factory oriented methods with respect to the color of the Vehicle.
To get a factory method that could handle Type and Color at the same time, the factory method
public Vehicle newVehicle(String type, String color) { ... }
might be added. Note that sometimes some combinations just don't make any sense, so it might not be worthwhile packing all factory methods down into a single factory method.
Any method in your factory object is not really a factory method unless it has the potential to return back more than one base type of the interface. Likewise it is not a factory method if you have to specify how to build the object outside of the method.
If you need to pass control of how to build a Vehicle to the client of your "it would have been a factory" method while providing some security they used it in a sane manner, you want the Builder pattern. An example of how a Builder Pattern differs can be seen in the client code below
VehicleBuilder builder = new VehicleBuilder();
builder.addDoor("driver");
builder.addDoor("passenger");
builder.paintVehicle("red");
Vehicle vehicle = builder.getVehicle();
Factory pattern is a vague term, no? There are Simple factories, Factory methods, and Abstract factories. I think you're talking about a Simple Factory here. https://www.codeproject.com/Articles/1131770/Factory-Patterns-Simple-Factory-Pattern
Here is an example of Java factory implementation.
Let's say we have a requirement to create multiple currencies support and code should be extensible to accommodate new Currency as well. Here we have made Currency as interface and all currency would be a concrete implementation of Currency interface.
Factory Class will create Currency based upon country and return concrete implementation which will be stored in interface type. This makes code dynamic and extensible.
Here is complete code example of Factory pattern in Java.
The Currency classes:
interface Currency {
String getSymbol();
}
// Concrete Rupee Class code
class Rupee implements Currency {
#Override
public String getSymbol() {
return "Rs";
}
}
// Concrete SGD class Code
class SGDDollar implements Currency {
#Override
public String getSymbol() {
return "SGD";
}
}
// Concrete US Dollar code
class USDollar implements Currency {
#Override
public String getSymbol() {
return "USD";
}
}
The Factory:
// Factory Class code
class CurrencyFactory {
public static Currency createCurrency (String country) {
if (country. equalsIgnoreCase ("India")){
return new Rupee();
}else if(country. equalsIgnoreCase ("Singapore")){
return new SGDDollar();
}else if(country. equalsIgnoreCase ("US")){
return new USDollar();
}
throw new IllegalArgumentException("No such currency");
}
}
// Factory client code
public class Factory {
public static void main(String args[]) {
String country = args[0];
Currency rupee = CurrencyFactory.createCurrency(country);
System.out.println(rupee.getSymbol());
}
}
Check out for more Java Factory pattern examples.

Using private constructors for factory methods?

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.

Encapsulating properties in a property/context class

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.

Java: Creating a subclass object from a parent object

Newbie Java question. Say I have:
public class Car{
...
}
public class Truck extends Car{
...
}
Suppose I already have a Car object, how do I create a new Truck object from this Car object, so that all the values of the Car object is copied into my new Truck object?
Ideally I could do something like this:
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck(c);
/* would like t to have all of c's values */
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Yes, just add a constructor to Truck. You will probably want to add a constructor to Car also, though not necessarily public:
public class Car {
protected Car(Car orig) {
...
}
public class Truck extends Car {
public Truck(Car orig) {
super(orig);
}
...
}
As a rule it's generally best to make classes either leaf (and you might want to mark those final) or abstract.
It looks as if you want a Car object, and then have the same instance turn into a Truck. A better way of doing this is to delegate behaviour to another object within Car (Vehicle). So:
public final class Vehicle {
private VehicleBehaviour behaviour = VehicleBehaviour.CAR;
public void becomeTruck() {
this.behaviour = VehicleBehaviour.TRUCK;
}
...
}
If you implement Cloneable then you can "automatically" copy an object to a instance of the same class. However there are a number of problems with that, including having to copy each field of mutable objects which is error-prone and prohibits the use of final.
If you are using Spring in your project you may use ReflectionUtils.
Yes, you have to do this manually. You'll also need to decide how "deeply" to copy things. For instance, suppose the Car has a collection of tyres - you could do a shallow copy of the collection (such that if the original object changes the contents of its collection, the new object would see the change too) or you could do a deep copy which created a new collection.
(This is where immutable types like String often come in handy - there's no need to clone them; you can just copy the reference and know that the contents of the object won't change.)
Would I have to write my own copy constructor? This would have to be
updated everytime Car gets a new field...
Not at all!
Try this way:
public class Car{
...
}
public class Truck extends Car{
...
public Truck(Car car){
copyFields(car, this);
}
}
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}
you can use reflection i do it and work fine for me:
public Child(Parent parent){
for (Method getMethod : parent.getClass().getMethods()) {
if (getMethod.getName().startsWith("get")) {
try {
Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType());
setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//not found set
}
}
}
}
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Essentially, yes - you can't just convert an object in Java.
Fortunately you don't have to write all the code yourself - look into commons-beanutils, specifically methods like cloneBean. This has the added advantage that you don't have to update it every time it gets a new field!
You could always use a mapping Framework such as Dozer. By default (without further configuration), it maps all fields of the same name from one object to another using the getter and setter methods.
Dependency:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
Code:
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
// ...
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck();
Mapper mapper = new DozerBeanMapper();
mapper.map(c, t);
/* would like t to have all of c's values */
You will need a copy constructor, but your copy constructor can use reflection to find the common fields between the two objects, get their values from the "prototype" object, and set them on the child object.
You could use the reflection API to loop through each of the Car fields and assign the value to the equivalent Truck fields. This can be done within truck. Further it is the only way to access the private fields of Car - at least in an automatic sense, providing that a security manager is not in place and restricting access to private field.
The solutions presented above have limitations you should be aware of. Here's a short summary of algorithms for copying fields from one class to another.
Tom Hawtin: Use this if your superclass has a copy constructor. If it does not you will need a different solution.
Christian: Use this if the superclass does not extend any other class. This method does not copy fields recursively upwards.
Sean Patrick Floyd: This is a generic solution for copying all fields recursively upwards. Be sure to read #jett's comment that a single line must be added to prevent an endless loop.
I reproduce Sean Patrick Floyd's analyze function with the missing statement:
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
Field[] declaredFields = current.getDeclaredFields();
for (Field field : declaredFields) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass(); /* The missing statement */
}
return map;
}
I know this is an OLD question, but I hate to leave out dated answers when things have improved.
Using JSON is much easier. Convert it to JSON and back again as child.
Here is an Android Kotlin Example.
val gson = Gson()
val childClass = gson.fromJson(
gson.toJson(parentObject),
object: TypeToken<ChildObject>(){}.type
) as ChildObject
I think in Java it would be basically.
Gson gson = new Gson()
ChildObject child = (ChildObject) gson.fromJson(
gson.toJson(parentObject),
TypeToken<ChildObject>(){}.getType()
)
And you're done, no messiness, just simple json in, json out.
If you don't have gson, I'm sure you have other json options available to you.
It's a WHOLE lot cleaner and faster than doing reflection and all that craziness.

Categories