From GoF chapter about the Factory Method pattern:
Define an interface for creating an object, but let subclasses decide which class to
instantiate. Factory Method lets a class defer instantiation to subclasses.
The idea is to let subclasses decided which class to instantiate, and GoF's implementation of the idea, is to provide an abstract method in the superclass, that subclasses need to override, and thus providing their own instantiation logic.
What I don't understand is, why implementing it using an abstract method, and not using a class member which is the factory. I'll explain.
This is the GoF way:
public abstract class Creator {
public void doStuff() {
Product product = createProduct();
/* etc. */
}
public abstract Product createProduct();
}
Usage:
MyCreator myCreator = new Creator() {
#Override
public Product createProduct() {
return new MyProduct();
}
}
myCreator.doStuff();
But why bother with the subclassing, etc.? I suggest this approach:
public class Creator {
private Factory factory;
/* constructor */
public Creator(Factory factory) {
this.factory = factory;
}
public void doStuff() {
Product product = factory.createProduct();
/* etc. */
}
}
And this is how you use it:
MyFactory myFactory = new MyFactory();
Creator creator = new Creator(myFactory);
creator.doStuff();
So what is the benefit in GoF's approach? Why not composing the Factory into the Creator class instead of expressing it using an abstract method?
Why not composing the Factory into the Creator class instead of expressing it using an abstract method?
Because in that case the client "knows" what Factory class to instantiate which defeats the whole purpose of the pattern. The whole idea is that the client is oblivious as what factory is built, it only makes a call to an Abstract class. Think that you plugin-in to your framework some third party factory provider and you have no idea what they instantiate (and also don't care) as long as serves the purpose.
The Factory Method Pattern is used to give subclasses control over the type of object they generate. In your case, it is not the subclass that controls the type of object but the user of the class.
The following example is copies from the Wikipedia entry on the Factory Method Pattern. We have a maze game which exists in two variants: the normal maze game and a magic maze game with adapted rules. The normal maze game consists of normal rooms and the magic maze game of magic rooms.
public class MazeGame {
public MazeGame() {
Room room1 = makeRoom();
Room room2 = makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}
protected Room makeRoom() {
return new OrdinaryRoom();
}
}
public class MagicMazeGame extends MazeGame {
#Override
protected Room makeRoom() {
return new MagicRoom();
}
}
By using the Factory Method Pattern we can make sure that the MagicMazeGame consists of MagicRooms but we can still re-use parts of the superclass.
In your suggestion the MazeGame class would be changed to:
public class MazeGame {
public MazeGame(RoomFactory factory) {
Room room1 = factory.makeRoom();
Room room2 = factory.makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}
}
and now it would be possible to do:
MazeGame game1 = new MazeGame(new MagicRoomFactory());
MazeGame game2 = new MagicMazeGame(new OrdinaryRoomFactory());
which is something you would like to prevent because then MazeGames with the wrong kind of rooms in it can be created.
its often useful in these types of situations to use actual English types for illustrations rather than more abstract terms like "Product"
So, let's take Pets, and say that every (sub-)type of Pet has a Home (eg. Dog has a Kennel).
For your example, we would have :
Public void doStuff() {
Home home = factory.createHome();
}
But in this case, where does the logic go that says Dogs get Kennels, and Birds get Cages? It would have to go in the factory object - which in turns means that the inheritance hierarchy of Pets would have to be explicitly repeated in the Factory logic. This in turn means that every time you add a new type of Pet, you'll have to remember to add that type to the Factory as well.
The factory method pattern means that you'd have something like :
public class Pet {
private String name;
private Home home;
public Pet(String name) {
this.name = name;
this.home = this.createHome();
}
public abstract Home createHome();
This allows that every time you create a new type of Pet, you can specify that Pet type's home without having to change any other class, and in the process also know that every Pet type DOES have a Home.
Eg. You would have :
public class Dog extends Pet {
public Home createHome() {
return new Kennel();
}
}
Edited to add Dog example
I think that the answers to this question aren't totally satisfactory, so here's my two cents...
To quote #Hoopje's answer, we might end up with something like this:
public class MazeGame {
public MazeGame(RoomFactory factory) {
Room room1 = factory.makeRoom();
Room room2 = factory.makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}
}
and then
MazeGame game1 = new MazeGame(new MagicRoomFactory());
MazeGame game2 = new MagicMazeGame(new OrdinaryRoomFactory());
As has been discussed above, this is nonsensical. However, I would contend that those last two lines don't make sense anyway, because in the OP's opinion, you would never need to create a MagicMazeGame at all. Instead you would just instantiate a MazeGame passing in new MagicRoomFactory().
MazeGame magicOne = new MazeGame(new MagicRoomFactory());
MazeGame normalOne = new MazeGame(new OrdinaryRoomFactory());
However, let's imagine that our MazeGame has multiple factories. Let's say that as well as needing to have a room factory, it also needs to have a points factory, and also a monsters factory. In this situation, we might end up with all of this being forced into the MazeGame constructor, like this:
public MazeGame(RoomFactory rmFactory, PointsFactory pointsFactory, MonsterFactory monstersFactory)
This is fairly convoluted, and instead it would be better to create concrete subclasses that each control their own type of game. That long constructor looks like a code smell to me too, though someone more knowledgeable might be able to add to this.
What's more, this means that whichever object is instantiating the game has to know about all of these inner-working classes, which breaks encapsulation.
All in all, by doing it this way we are giving too much control to the client, who doesn't want to know about all of these implementation details.
That's how I see it anyway...
Related
I am using the Builder Pattern since time ago, but these days one of my collegues reach me with a question to which I never thought about, and is about the #newBuilder() function in the Builder Pattern.
I've seen in several forums, tutorials, and even APIs, that when using the Builder Pattern, a structure like this is usually used:
Car car1 = new CarBuilder().newBuilder().twoDoors().fourWheels().build();
Usually, inside of the #newBuilder() function, there is a code like this:
public static CarBuilder newBuilder(){
return new CarBuilder();
}
The question is, why should be needed a #newBuilder() function in the Builder class? Is it a good practice to have it, or is needed only when overloading is applied? I mean, just in the cases where I need to overload the #newBuilder() having 2 or 3 different #newBuilder() functions with different parameters.
What if I will have only one #newBuilder() function in the Builder class? Should I implement it, or can I avoid it and do something like:
Car car1 = new CarBuilder().twoDoors().fourWheels().build();
The question of my colleague was: If I implement the #newBuilder() function, am I falling in redundancy with the first example if I will only have one #newBuilder() function in my Builder class?
What you think about this? Should I remove it or it is justified to have the #newBuilder() function despite of I have only one implementation of it without overloading?
Thanks!
Note that this:
Car car1 = new CarBuilder().newBuilder().twoDoors().fourWheels().build();
Is definitely redundant, but not because the newBuilder() method exists. The problem is your code is essentially this:
CarBuilder builder1 = new CarBuilder();
CarBuilder builder2 = builder1.newBuilder();
Car car1 = builder2.twoDoors().fourWheels().build();
In other words, you're creating two instances of CarBuilder. Also, you're calling a static method on an instance reference, which is frowned upon. With your current setup, your code should be either:
Car car1 = new CarBuilder().twoDoors().fourWheels().build();
OR:
Car car1 = CarBuilder.newBuilder().twoDoors().fourWheels().build();
Which style you choose is up to you. However, if you choose to use the second approach (the static factory method newBuilder()), then typically the builder's constructor is made private, or at least package-private, so that new CarBuilder() cannot be used by external code.
So, I would say "no", having newBuilder() is not redundant in and of itself, as long as you use it correctly. It's simply an alternative way of creating a builder instance without calling the constructor directly. Note using the static factory method approach may aid in readability, because you can name the method something more descriptive. You may not see that advantage unless you have a significant number of different factory methods with different semantics, however.
Another thing to consider is where to place the newBuilder() static method. If CarBuilder and Car are extremely coupled, then many developers will put the static method in the Car class instead of the CarBuilder class (if not just nest the latter in the former).
For example:
package sample;
public final class Car {
public static CarBuilder newBuilder() {
return new CarBuilder();
}
private final int numberOfDoors;
private final int numberOfWheels;
Car(CarBuilder builder) {
this.numberOfDoors = builder.numberOfDoors;
this.numberOfWheels = builder.numberOfWheels;
}
// getters and setters omitted for brevity
}
package sample;
public final class CarBuilder {
private int numberOfDoors; // should initialize to sensible default
private int numberOfWheels; // should initialize to sensible default
CarBuilder() {}
public CarBuilder twoDoors() {
numberOfDoors = 2;
return this;
}
public CarBuilder fourWheels() {
numberOfWheels = 4;
return this;
}
public Car build() {
return new Car(this);
}
}
Which could then be used like so:
Car car1 = Car.newBuilder().twoDoors().fourWheels().build();
I am learning design patterns newly & I am trying to understand the difference between Simple Factory & Factory Method Pattern. First I want to clear that , I tried reading lot of articles from Stack-overflow and other sites regarding the same but that doesn't helped me.
Here is my question:
Lets consider I have a product hierarchy as shown below:
I have written a simple Factory class as shown below
public class SimpleItemFactory {
static Item getItem(String type) {
if(type.equals("Cake")) {
return new Cake();
}else if(type.equals("Chocolate")) {
return new Chocolate();
}else {
return null;
}
}
}
so now I have all the object creation in one place , so if tomorrow any changes occurs[Like constructor needs one parameter] we need to change in only one place. But it breaks OPEN CLOSED principle as if tomorrow we add more item we need to change getItem() methods if condition. So we go for Factory Method Pattern
We create Factory class as shown below:
public abstract class ItemFactory {
abstract Item getItem();
}
class CakeFactory extends ItemFactory {
#Override
Item getItem() {
return new Cake();
}
}
class ChocolateFactory extends ItemFactory {
#Override
Item getItem() {
return new Chocolate();
}
}
class Client{
public static void main(String[] args) {
Item chocolate = new ChocolateFactory().getItem();
System.out.println(chocolate);
}
}
Now when the client want to add new Item called IceCream, they just create new Factory called IceCreamFactory and create IceCream from that as shown below:
class IceCreamFactory extends ItemFactory{
#Override
Item getItem() {
return new IceCream();
}
}
class Client{
public static void main(String[] args) {
Item iceCream = new IceCreamFactory().getItem();
System.out.println(iceCream);
}
}
Is my understanding correct?
We satisfied Open closed principle here, but for each product(Item) we need one Factory class, does not it become manageable nightmare?
NOTE: Article I was referring https://www.codeproject.com/Articles/1135918/Factory-Patterns-Factory-Method-Pattern?msg=5380215#xx5380215xx
Your understanding actually is correct, just you need to note that every design pattern is made to solve at least one single issue, sometimes it could bring with it some other complexities or side effects, which means there is no perfect design pattern that could solve every problems.
For learning purposes you apply design patterns one by one (that makes the real power of design patterns sames to be shy or hiding), however in a real world context design patterns are mixed together (or even you can invent a new one :p) for the purpose of creating something that satisfy most your needs and becomes near to ideal, you can meet for example the Builder pattern mixed with Factory pattern or Factory pattern with Strategy pattern, or even the three of them mixed together...
For your case here I propose for example to use Factory Method Pattern together with Simple Factory Pattern combined with Dependency Injection Pattern to create something totally beautiful and at the same time satisfying the Open closed principal.
class ItemFactoryContainer() {
private Map<String, ItemFactory> factories = new HashMap<>();
public void register(String name, ItemFactory factory) {
factories.put(name, factory);
}
public ItemFactory getFactory(String name) {
return factories.get(name);
}
}
public class ItemFactoryTest {
public static void main(String...args) {
ItemFactoryContainer factoryContainer = new ItemFactoryContainer();
factoryContainer.register("choclate", new ChocolateFactory ());
factoryContainer.register("cake", new CakeFactory ());
factoryContainer.register("iceCream", new IceCreamFactory ());
Chocolate choclate = factoryContainer.getFactory("choclate").getItem();
Cake cake = factoryContainer.getFactory("cake").getItem();
}
}
Answers (by #Mouad EL Fakir and #François LEPORCQ) are about the static factory. That is your first part of the code.
There are two more flavors namely Factory Method and Abstract Factory)
Second part of your code is using CakeFactory and ChocolateFactory, you are trying to use Factory Method (though your naming suggests Abstract Factory). The usage of factory method getXXX() here is incorrect. The purpose of these patterns is different. In your code you are not achieving anything but increasing number of classes. (though increased number of classes and parallel hierarchies is documented as cost associated with Factories)
I have answered a similar questions recently see if those answers are helpful
Role of Creator in Factory Pattern
What are the real benefits of using the Abstract Factory in the following example, instead of the factory method?
I think in your example a factory seem useless because your Cake and Chocolate constructors don't need any args.
A factory is useful when you want to construct a complex object with many args to respect the DIP (Dependency Inversion Principle) and avoid embarrassing couplings.
In addition, your example seems to violate the LSP (Liskov Substitution Principle). Cake and Chocolate classes have nothing in common, and as evidence, your abstract super class is named Item which is a very generic name.
For me, with complex uncommon objects, the choice of one factory by class is better, and effectively respect the OCP (Open Closed Principle).
Your first example can be useful to instantiate classes which inherits the same superclass, but using your classes as arg and reflection (using java.lang.reflect) to call the constructor not just using String evaluation. (Your IDE is not able to autocomplete that) and in case of no match don't return null, Throw an IllegalArgumentException, it's more correct.
Like this :
import java.lang.reflect.Constructor;
public class SimpleItemFactory {
public <T extends Item> T createItem(Class<? extends Item> itemClass) {
try {
// construct your dependencies here
// and inject them in the getConstructor
Constructor<? extends Item> constructor = itemClass.getConstructor();
return (T)constructor.newInstance();
} catch (Exception e) {
throw new IllegalArgumentException();
}
}
}
and use it like this :
class Client {
public static void main(String[] args) {
SimpleItemFactory factory = new SimpleItemFactory();
IceCream iceCream = factory.createItem(IceCream.class);
System.out.println(iceCream);
Cake cake = factory.createItem(Cake.class);
System.out.println(cake);
Chocolate chocolate = factory.createItem(Chocolate.class);
System.out.println(chocolate);
}
}
If you have no dependencies you can implement the createItem() method as static directly in your abstract Item class.
See this book, it's a great resource : Head First Design Patterns
OCP is just Open for extension Close for modification Principle. If you need to open for modification your factory to add a new class (a new case to manage in a switch or a if), no, your factory is not "OCP".
You sould'nt calculate a tax in a constructor, a constructor should just... construct an object.. You could use a pattern like strategy to have many taxesCalculator and inject them into a constructor, with an IOC (Inversion of Control) mechanism like dependencies injection or in a simple way with.....a factory (it's acceptable), but not with a simple static method in your class.
I'm sorry for my bad english, it's difficult for me to answer to a complex question like this.
Ok so I have a large structure of classes that looks something like THIS
Its for school and my instructor likes Starcraft, so lets just go with it.
Anyway I have a method in the GeneratorBuilding Class that is supposed to be able to instantiate a new Marine Object. However I need to know how many resources a Marine object costs.
I have an abstract int method in the abstract Unit class called unitCost(). Then the Marine class overrides this method and returns a value like 50.
I am looking for a way to have my GeneratorBuilding class get the return value for the unitCost() method in the Marine class without calling any specific Marine object.
I know that I could probably create a marine object and then ask how much it costs and then if I dont have the resources I would delete the object instead of pushing it into an ArrayList. But this seems almost like a workaround.
EDIT: The whole point is to be able to let ALL of my concrete classes inherit and override the UnitCost() method. So I could make it static but that ruins the whole point of an inheritance structure...
EDIT2: Since there was a request for example code (not exactly hard to imagine)
public void makeMarine(){
//uses resources and throws exception etc if there are not enough resources
Game.useResources(Marine.unitCost());
//creates a marine
Game.addMarine();
}
You can do this by declaring a specifically named static field in each class, and getting it through reflection}.
Suppose your classes look like this:
class ClassNumber1 {
public static final int cost = 123;
}
class ClassNumber2 {
public static final int cost = 321;
}
Then you can obtain their cost fields like this:
public static <T> int getCost(Class<T> cl) throws Exception {
// This is oversimplified: you need to check that the class
// indeed has a field called "cost" by null-checking the return value
// of getField(), verifying your cast, catching exceptions, and so on.
// But this will work in a "closed" system, when you know for sure
// that an int constant field does exist:
return (int)cl.getField("cost").get(null);
}
You call the method as follows:
System.out.println(getCost(ClassNumber1.class));
System.out.println(getCost(ClassNumber2.class));
Here is a demo on ideone.
If you really want a good, abstract OO solution to this problem, you should use the Abstract Factory Pattern.
Basically, this means you create a "factory" class whose only job is to create a specific type of unit. The nice thing about factory classes is that you can create an interface to represent your entire set of factories, and then pass around instances of the factories—which isn't really something you can do with normal class constructors.
A common pattern (which I would recommend here) is to use Anonymous Inner Classes with your abstract factory class or interface to create single instances of the "factory" for each unit type.
Here's a bit of example code to get you started:
/**
* Abstract class for Starcraft units
*/
public abstract class AUnit {
// . . .
}
/**
* Abstract factory for creating Starcraft units
*/
public abstract class AUnitFactory {
public abstract int unitCost();
public abstract AUnit createUnit();
}
public class Marine extends AUnit {
public static final int COST = 50;
/**
* Using an anonymous inner class to create an
* AUnitFactory instance for Marines
*/
public static final FACTORY = new AUnitFactory() {
public int unitCost() { return COST; }
public AUnit createUnit() { return new Marine(); }
}
// . . .
}
public class Zergling extends AUnit {
public static final int COST = 25;
/**
* Using an anonymous inner class to create an
* AUnitFactory instance for Zerglings
*/
public static final FACTORY = new AUnitFactory() {
public int unitCost() { return COST; }
public AUnit createUnit() { return new Zergling(); }
}
// . . .
}
/**
* Starcraft game!
*/
public class Game {
public addUnit(Player player, AUnitFactory unitFactory) {
// Get unit's cost
int cost = unitFactory.unitCost();
// Now deduct it from the player's resources
// . . .
// Create the unit
AUnit unit = unitFactory.createUnit();
// Now add the unit to the game for the given player
// . . .
}
// . . .
}
Now you could do something like Game.addUnit(player1, Zergling.FACTORY) or Game.addUnit(player2, Marine.FACTORY).
The nice thing is that you can pass the FACTORY instances around since they're just objects of type AUnitFactory. This means you could do something like have a combo box to select a unit type, and then a button which creates one of whichever unit type is currently selected in the combo box when clicked.
This is exactly what class methods are for. In a class method, unitCost() is a method of the Marine class itself (i.e. static public int UnitCost()), so you can call Marine.unitCost(), rather than m =new Marine() and then m.UnitCost().
Cool instructor. Wish I had one when I was taking OO.
Can somebody help a novice programmer to understand if his solution is correct?
My question is similar to the the following two:
What's wrong with overridable method calls in constructors?
Factory pattern in C#: How to ensure an object instance can only be created by a factory class?
Problem: I want to have subclasses which will differ only in their initialisation method. However, I also want to prevent instantiating these classes without initialization. In other words, I want to ensure, that some "initialize()" method will always be called after instantiation of a subclass:
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
loadData(); // should be called to initialise class fields and ensure correct work of other class methods
}
protected abstract loadData(){
... //uses dataSource
}
}
So I decided to perform initialization on a constructor. It worked (now I know that it's a very bad practice) until I created a subclass where the initialize method used some additional parameters:
public class DataFromSpecificSources extends Data {
private Parameter dataSource2;
public DataFromSpecificSources(parameter1, parameter2){
this.dataSource2 = parameter2; // I can't put it here because the constructor is not called yet
super(parameter1); // this, of course, will not work
}
#Override
private void loadData(){
... // uses both dataSource 1 and 2
// or just dataSource2
}
}
This, of course, is not going to work. And I started searching for a right pattern... After I read the answers on questions posted before, I decided to use the factory and limit visibility of the subclass constructor to the package:
My solution:
// factory ensures that loadData() method will be called
public class MyDataFactory(){
public Data createSubClass(parameter1,parameter2){
Data subClass;
if (parameter2 != null){
subClass = new DataFromSpecificSources(parameter1, parameter2);
subClass.loadData();
} else {
subClass = new AnotherSubClass(parameter1);
subClass.loadData()
}
return subClass;
}
}
public abstract class Data {
protected Parameter dataSource;
Data(parameter1){
this.dataSource = parameter1;
}
// I don't call it in constructor anymore - instead it's controlled within the factory
protected abstract loadData(){
... //uses dataSource
}
}
public class DataFromSpecificSources {
private Parameter dataSource2;
protected DataFromSpecificSources(){}
// now this constructor is only visible within package (only for the factory in the same package)
DataFromSpecificSources(parameter1, parameter2){
super(parameter1); // it does not initialise data anymore
this.dataSource2 = parameter2;
}
#Override
protected void loadData(){
... // uses dataSources 1 and 2
}
}
Now factory ensures that subclasses will be initialized (data will be loaded) and instantiation of subclasses is not allowed in other packages. Other classes have no access to constructor of subclasses and are forced to use factory to get an instance of a subclass.
I just wanted to ask if my solution is correct (logically) and Factory method with subclass constructor visibility limited to the package is right choice here?! Or there is any other more effective pattern solving the problem?!
Using a factory is definitely a step in the right direction. The issue I see is that what happens when you want to add a third class that takes a third parameter. Now your Factory is either going to have to have a second overloaded createSubClass method taking the third parameter, or all your code is going to have to be rewritten to provide the third parameter. Additionally you are forcing anyone using the Factory to specify null for the second parameter even if they only want the single parameter class.... when you get to the class that takes 15 parameters how are you going to remember which parameter is which
The solution to this is to use the Builder pattern instead.
public class MyDataBuilder(){
private parameter1 = null;
private parameter2 = null;
public MyDataBuilder withParameter1(parameter1) {
this.parameter1 = parameter1;
return this;
}
public MyDataBuilder withParameter2(parameter2) {
this.parameter2 = parameter2;
return this;
}
public Data createSubClass(){
Data subClass;
if (parameter2 != null){
subClass = new DataFromSpecificSources(parameter1, parameter2);
} else {
subClass = new AnotherSubClass(parameter1);
}
subClass.loadData();
return subClass;
}
}
Now the code creating the Data instances can work like so:
Data data = new MyDataBuilder().withParameter1(param1).withParameter2(param2).create();
or
Data data = new MyDataBuilder().withParameter1(param1).create();
And that code is future-proofed for when you add parameter3... and you can even have the builder with a non-null default for parameter3 if you so need that.
The next thing you notice is that you now have this nice Builder object that contains all the required parameters... so now you can add getters to the Builder and just pass the Builder as the constructor parameter, e.g.
public class DataFromSpecificSources {
...
DataFromSpecificSources(MyDataBuilder builder){
...
}
...
}
So that you now almost have a standard constructor signature
Now for some Java specific improvements. We can make the builder not need to know about the sub-classes at all!
Using a DI framework we can inject the classes that implement the Data interface / abstract class into the Builder and then just iterate through each class until we find a class that supports the configuration of the Builder instance.
The poor-man's DI framework is the /META-INF/services contract and the ServiceLoader class available since JRE 1.6 (though the core logic has been in Java since 1.2)
Your builder's create method will then look a little something like
public Data create() {
for (DataFactory factory: ServiceLoader.load(DataFactory.class)) {
if (factory.canCreate(this)) {
Data result = factory.newInstance(this);
result.loadData();
return result;
}
}
throw new IllegalStateException("not even the default instance supports this config");
}
Whether you want to go to that extreme is questionable... but since you might come across it at some point in time when looking at other people's code, it is probably a good time to point it out to you now.
Oh, the reason why we have to add a Factory class to be looked up by the ServiceLoader is because ServiceLoader expects to call the default constructor, and we have hidden the default constructor so we use a Factory class to do the work for us and allow us to keep the constructor hidden.
There is nothing preventing the Factory classes from being static inner classes in the Data classes (which gives them great visibility on the class they are creating), e.g.
public class UberData extends Data {
private UberData(MyDataBuilder config) {
...
}
public static class Factory extends DataFactory {
protected Data create(MyDataBuilder config) {
return new UberData(config);
}
protected boolean canCreate(MyDataBuilder config) {
return config.hasFlanges() and config.getWidgetCount() < 7;
}
}
}
As we can then list in META-INF/services/com.mypackage.DataFactory
com.mypackage.UberData.Factory
com.mypackage.DataFromSpecificSources.Factory
com.some.otherpackage.AnotherSubClass.Factory
The best bit about this type of solution is it allows adding additional implementations just by adding those implementations to the classpath at run-time... i.e. very loose coupling
I have the following classes
class Person {
private String name;
void getName(){...}}
class Student extends Person{
String class;
void getClass(){...}
}
class Teacher extends Person{
String experience;
void getExperience(){...}
}
This is just a simplified version of my actual schema. Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.
void calculate(Person p){...}
Now I want to access the methods of the child classes using this parent class object. I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT.
I guess I simplified too much in the above example, so here goes , this is the actual structure.
class Question {
// private attributes
:
private QuestionOption option;
// getters and setters for private attributes
:
public QuestionOption getOption(){...}
}
class QuestionOption{
....
}
class ChoiceQuestionOption extends QuestionOption{
private boolean allowMultiple;
public boolean getMultiple(){...}
}
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption().getMultiple())
{...}
}
}
The if statement says "cannot find getMultiple for QuestionOption." OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children)
NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance. The best way would be to restructure your application design so that there are NO parent to child dependencies. A parent should not ever need to know its children or their capabilities.
However.. you should be able to do it like:
void calculate(Person p) {
((Student)p).method();
}
a safe way would be:
void calculate(Person p) {
if(p instanceof Student) ((Student)p).method();
}
A parent class should not have knowledge of child classes. You can implement a method calculate() and override it in every subclass:
class Person {
String name;
void getName(){...}
void calculate();
}
and then
class Student extends Person{
String class;
void getClass(){...}
#Override
void calculate() {
// do something with a Student
}
}
and
class Teacher extends Person{
String experience;
void getExperience(){...}
#Override
void calculate() {
// do something with a Teacher
}
}
By the way. Your statement about abstract classes is confusing. You can call methods defined in an abstract class, but of course only of instances of subclasses.
In your example you can make Person abstract and the use getName() on instanced of Student and Teacher.
Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition". That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy. I submit that this is a type-safe, but often very bad, approach. You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).
I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java. They all suck, because Java sucks at variant types. So far the only JVM language that gets it right is Scala.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
The Scala creators actually wrote a paper about three of the eight ways. If I can track it down, I'll update this answer with a link.
UPDATE: found it here.
Why don't you just write an empty method in Person and override it in the children classes? And call it, when it needs to be:
void caluculate(Person p){
p.dotheCalculate();
}
This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.
I had the same situation and I found a way around with a bit of engineering as follows - -
You have to have your method in parent class without any parameter and use - -
Class<? extends Person> cl = this.getClass(); // inside parent class
Now, with 'cl' you can access all child class fields with their name and initialized values by using - -
cl.getDeclaredFields(); cl.getField("myfield"); // and many more
In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.
Another thing you might need to use is Object obj = cl.newInstance();
Let me know if still you got stucked somewhere.
class Car extends Vehicle {
protected int numberOfSeats = 1;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
public void printNumberOfSeats() {
// return this.numberOfSeats;
System.out.println(numberOfSeats);
}
}
//Parent class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
System.out.println(licensePlate);
}
public static void main(String []args) {
Vehicle c = new Vehicle();
c.setLicensePlate("LASKF12341");
//Used downcasting to call the child method from the parent class.
//Downcasting = It’s the casting from a superclass to a subclass.
Vehicle d = new Car();
((Car) d).printNumberOfSeats();
}
}
One possible solution can be
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption() instanceof ChoiceQuestionOption)
{
ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
boolean result = choiceQuestion.getMultiple();
//do something with result......
}
}
}