Is it correct to use java.util.function.Function to implement Factory Design Pattern
In the following example, I've used Function reference to instantiated a Person type object.
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Function<String , Person> myFunc = (String s) -> new Person(s);
Person p = myFunc.apply("John");
System.out.println(p.getName());
}
}
class Person{
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
The factory design pattern is used to hide implementation logic behind an object factory and its power is to use inheritance to achieve this. Say you would have more than one type of person, e.g. a SmartPerson and a DumbPerson (implementing the same Person base class). One could ask the factory to create either a smart or a dumb person without ever knowing about the implementation differences, since all it ever returns is a Person object.
You can instantiate a person with a function referring to the constructor, but this pattern is about the location of the object creation, allowing you to hide certain implementation logic.
This hiding of logic behind a factory saves you a lot of time in the future where different classes may use the factory to create persons, because a change to the way you create a person would only require you to modify the creation methods in the factory and does not affect each individual class using the factory.
#Test
public void testSimpleFactory() {
PersonFactory personFactory = new PersonFactory();
Person person = personFactory.createPerson("dumb");
person.doMath(); // prints 1 + 1 = 3
}
public class PersonFactory {
public Person createPerson(String characteristic) {
switch (characteristic) {
case "smart":
return new SmartPerson();
case "dumb":
return new DumbPerson();
default:
return null;
}
}
}
public interface Person {
void doMath();
}
public class SmartPerson implements Person {
#Override
public void doMath() {
System.out.println("1 + 1 = 2");
}
}
public class DumbPerson implements Person {
#Override
public void doMath() {
System.out.println("1 + 1 = 3");
}
}
Related
The Problem
I'm trying to create an application where an object class can implement some
operations from the total pool of available operations. The end goal is to not have any code duplication and to abide by the laws of OOP as much as possible.
In more detail, I'm trying to make a search engine using Lucene. Lucene
uses many indices. I've already implemented a simple structure where different index-objects inherit the methods of a parent class. The problem is that, whatever method is implemented in that parent class, it automatically becomes available for all subclasses to use. I want to give the option to the user to determine if he wants to do a phrase search, a term search or whatever else there is available for that specific index. The catch is, some indices shouldn't have the option to conduct phrase search, for example.
First Thoughts
I've thought of implementing something close to the Composite pattern,
as described by the GoF. I would implement the search operations (e.g. term search, phrase search) as primitive operations implementing some Component class and add these primitive objects later on to a Composite object. The Composite object will be implementing the same Component class as the primitives.
public abstract class Index {
public Index(String indexPath) {
// Constructor using the information provided by the subclass
}
public void phraseSearch(...) {
// Do the operation
}
public void termSearch(...) {
// Do the operation
}
public void categorySearch(...) {
// Do the operation
}
}
public class ReviewIndex extends Index {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends Index {
public TipIndex() {
super("./tip_index/");
}
}
Expected Outcome
The class ReviewIndex shouldn't be able to perform a categorySearch but be
able to execute phraseSearch and termSearch. Respectively, the TipIndex class
should be able to execute some of the parent class methods.
Final Thoughts
I know that in my solution there is no code duplication but there
are useless methods being generated each time a new index object is created.
Thank you all in advance!
P.S. If you think the Composite pattern is the way to go, in which way would you actually add the primitive objects to the composite class and in which way would you invoke them when need to?
All methods defined in a superclass are available at deriving classes but with Java 8 you might be able to get something like this by using default-methods in interfaces. So instead of one abstract class containing all possible methods you might implement four interfaces
public interface Searchable {
public String getIndexPath();
}
public interface PhraseSearchable extends Searchable {
public default void phraseSearch() {
String indexPath = getIndexPath();
// do the search
}
}
public interface TermSearchable extends Searchable {
public default void termSearch() {
String indexPath = getIndexPath();
// do the search
}
}
public interface CategorySearchable extends Searchable {
public default void categorySearch() {
String indexPath = getIndexPath();
// do the search
}
}
To avoid duplicate code you can create an abstract class
public abstract class AbstractSearchable implements Searchable {
private String indexPath;
public AbstractSearchable(String indexPath) {
this.indexPath = indexPath;
}
// other methods that might be useful
}
Your actual classes can then implement the corresponding interfaces
public class ReviewIndex extends AbstractSearchable implements CategorySearchable {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends AbstractSearchable implements PhraseSearchable, TermSearchable {
public ReviewIndex() {
super("./review_index/");
}
}
If this is possible depends heavily on the actual implementation of the search methods. Interfaces can't contain any members, etc. so these methods must be able to run for themselves (like a static method without using any static members of the class). You might to overcome this problem by adding more methods to the Searchable interface that provide the data and do the implementation in the abstract class but that might expose internal stuff to the public because all the declared methods in an interface are public.
If you don't want to use categorySearch(...) for ReviewIndex class then create one more hierarchy where you keep the categorySearch(...) method.
Example:
public abstract class Index {
public Index(String indexPath) {
// Constructor using the information provided by the subclass
}
public void phraseSearch(...) {
// Do the operation
}
}
// Give a meaningful Name
public abstract class IndexChild1 extends Index {
public void categorySearch(...) {
// Do the operation
}
}
// Give a meaningful Name
public abstract class IndexChild2 extends Index {
public void termSearch(...) {
// Do the operation
}
}
public class ReviewIndex extends IndexChild1 {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends IndexChild2 {
public TipIndex() {
super("./review_index/");
}
}
You can use Composite pattern if you need to have the same objects and use them as you wish in your ReviewIndex and TipIndex classes. you can use a list which implies aggregation and you can use one instantiation of each object(PhraseSeach, TermSearch, CategorySearch) in any order you want.
here is the code:
import java.util.ArrayList;
import java.util.List;
public class Main{
public static void main(String[] args) {
Main m = new Main();
m.run();
}
public void run() {
ReviewIndex ri = new ReviewIndex();
}
public interface ISearch {
public void search();
}
public class SearchComposite implements ISearch{
private List<ISearch> l = new ArrayList<ISearch>();
public SearchComposite(String index) {
System.out.println(index);
}
public int addSearch(ISearch search) {
l.add(search);
return this.l.size() - 1;
}
public List<ISearch> getSearch(){
return this.l;
}
public void search() {
System.out.println("search");
}
}
public class CategorySearch implements ISearch{
#Override
public void search() {
System.out.println("category search");
}
}
public class PhraseSearch implements ISearch{
#Override
public void search() {
System.out.println("phrase search");
}
}
public class TermSearch implements ISearch{
#Override
public void search() {
System.out.println("term search");
}
}
CategorySearch cs = new CategorySearch();
TermSearch ts = new TermSearch();
PhraseSearch ps = new PhraseSearch();
public class ReviewIndex {
SearchComposite sc = new SearchComposite("./review_index/");
public ReviewIndex() {
int p = sc.addSearch(ps);
int t = sc.addSearch(ts);
sc.search();
List<ISearch> s = sc.getSearch();
s.get(p).search();
s.get(t).search();
}
}
public class TipIndex {
SearchComposite sc = new SearchComposite("./tip_index/");
public TipIndex() {
int p = sc.addSearch(ps);
int t = sc.addSearch(ts);
int c = sc.addSearch(cs);
sc.search();
List<ISearch> s = sc.getSearch();
s.get(p).search();
s.get(t).search();
s.get(c).search();
}
}
}
the output of the code above is:
./review_index/
search
phrase search
term search
and we have used the same CategorySearch, TermSearch and PhraseSearch for ReviewIndex and TipIndex classes.
public class Player implements Comparable<Player> {
//Fields
private Name name;
private Rollable rollable;
//Constructors
public Player() {
name = new Name();
rollable = new Rollable();
}
public Player(Name name) {
this.name = name;
rollable = new Rollable();
}
public Player(Name name, Rollable rollable) {
this.name = name;
this.rollable = rollable;
}
Hello, for my constructors where i have put rollable = new Rollable(); I am getting an error which states that it Cannot instantiate the type rollable.
Below i have added the JUnit test and i will also add the code for the Rollable class
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.
getName());
assertTrue("Player's rollable field should be initialised with an. implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
#Test
public void testCustomConstructor1arg() {
Name n = new Name("Joe", "Bloggs");
Player p = new Player(n);
assertSame("Player's name field should be initialised with and return the same object received by the constructor", n, p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
Now below is the JUnit test for the default constructor whcih is also giving me the failure of Players rollable field should be initialised with an implementing instance of the Rollable interface, however, all of my other JUnit tests are passing.
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
The code for my Rollable class is as below;
public interface Rollable {
public void roll();
public int getScore();
}
The methods for my rollable code are as below;
//Methods
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public Rollable getRollable() {
return rollable;
}
public void rollDice() {
rollable.roll();
}
public int getDiceScore() {
return rollable.getScore();
}
All help will be appreciated as i am struggling with the failures, thank you.
Your getRollable() method is:
public Rollable getRollable() {
return rollable;
}
So, if you call that from a constructor, for example:
public Player() {
name = new Name();
rollable = getRollable();
}
then rollable will be assigned the value of rollable, which is by default null.
As such, when you call getRollable() again in the test, you get back the value you assigned to the field - null - and by definition - null instanceof Rollable is false.
Instead, you need to create a new instance of Rollable, for example:
rollable = new Rollable();
(Don't know if it is directly instantiable. You've not provided the declaration of the Rollable class).
Your Rollable is an interface, and in Java you can only create instances of non-abstract classes.
So you need to write at least one class that implements Rollable. Of this class, you can create instances.
Why is that so?
Have a look at e.g. the Comparable interface (serving me as an analogon to your Rollable). Comparable denotes classes that support some kind of greater / equal / less than comparison, by requiring the class to have a method named compareTo(). If you were to instantiate a Comparable, what would you expect to be the result? A String, a Long, a Double or what? And the same applies to your Rollable.
An interface defines some requirements that implementing classes must fulfill, but they don't denote classes themselves, so you can't create (direct) instances of interfaces.
I would like to use the builder pattern in some upcoming work that I have which has several classes in a hierarchy. The base class will have at least 9 fields to start, and the various sub-classes may add between 2-4 more fields each. This would get out of hand very quickly and the builder pattern is appealing to me for this exact reason. I got some initial exposure to the builder pattern in books and articles. They were helpful, but had nothing on how to extend this pattern. I tried to implement this by myself, but I ran into trouble with the constructors of each of the sub-classes because I didn't get how to pass the collected data in the builder to super class. I looked on SO for some answers, and here's what I found.
This one is from SO 24243240 where an example of how to extend an abstract class with an abstract builder is given. It is also based on this blog post.
public abstract class AbstractA {
protected String s;
protected int i;
protected AbstractA() {
}
protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
protected T object;
protected B thisObject;
protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
protected ABuilder() {
object = getObject();
thisObject = thisObject();
}
public B withS(String s) {
object.s = s;
return thisObject;
}
public B withI(int i) {
object.i = i;
return thisObject;
}
public T build() {
return object;
}
}
}
public final class ConcreteA extends AbstractA {
private String foo;
protected ConcreteA() {
}
public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
#Override protected ConcreteA getObject() {
return new ConcreteA();
}
#Override protected Builder thisObject() {
return this;
}
public Builder() {
}
public Builder withFoo(String foo) {
object.foo = foo;
return this;
}
}
}
And then in client code, it would look like...
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();
I like this example because it allows you to easily extend these classes, but it also seems to me that this defeats the purpose of using the builder pattern because the methods withS(String s) and withI(int i) act alot like setter methods. Also, this method leaves the fields of the base class and the builder class as protected rather than private.
Here's one from SO 17164375
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
I like that this one seemingly adheres more closely to the builder pattern described by Josh Bloch and it also allows you to simply pass the builder into the constructor for the class you want to instantiate. This would be a nice way to do some validation inside the builder before instantiating the object in the call to build(). At the same time though, this example shows how you can extend the builder pattern with concrete classes, and when you do that the potential for all the nastiness that comes with extending concrete classes (e.g. inconsistent interfaces, inheriting methods which can corrupt the state of your object, etc.)
So my question is there a way to implement an abstract class with an abstract builder that also allows you to pass in a reference to a builder in the constructor for the base class? Something like:
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
I realize that you can't instantiate an object the way that I've shown here, but is there some other way to do it I mean? Is this possibly where a factory would go? Maybe I just have the wrong assumptions about the builder pattern in general. :) If that's the case, is there a better direction to take?
Your first example is not bad, but I don't think it is what you are looking for.
I am still a little unsure of exactly what you want, but seeing your examples do not work for you, I thought I'd give you one or two of my own. :)
class ParentBuilder{
public ConcreteParent build(){
ConcreteParent parent = new ConcreteParent();
parent.setFirst(1);
parent.setSecond(2);
parent.setThird(3);
return parent;
}
}
class ChildBuilder{
public ConcreteChild build(ParentBuilder parentBuilder){
ConcreteParent parent = parentBuilder.build();
ConcreteChild child = new ConcreteChild();
child.setFirst(parent.getFirst());
child.setSecond(parent.getSecond());
child.setThird(parent.getThird());
child.setFourth(4); //Child specific value
child.setFifth(5); //Child specific value
return child;
}
}
Any new type, would have its own builder, taking in its parent's builder.
As you can see this is similar to:
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
In your example.
This however, quickly gets out of hand as well, increasingly for the number of variables and subclasses.
An alternativ, would be to use dynanic variables, have a look at this: http://martinfowler.com/apsupp/properties.pdf
Martin Fowler writes a great article specifying all the pros and cons.
Anyways, here's my second example:
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}
The magic here is, you (might) no longer need all these subclasses.
If these subclasses' behavior does not change, but only their variables, you should be fine using a system like this.
I strongly advise that you read Martin Fowler article on the subject though, there are good places and bad places to do this, but I think this is a good one.
I hope this brings you closer to an answer, good luck. :)
Let's say we have a class with the following method:
public class Entry {
private String name;
public static Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
This class may be subclassed (e.g. SubEntry), and the logic behind "getOrCreate" does not change. But the subclasses should not return a new object of the type Entry, but of the type of the respective subclass (e.g. return SubEntry(name))
How can I realize this without reimplementing the method getOrCreate for every subclass of Entry? Is there a term for this kind of technique?
Subclassing Entry does not affect the getOrCreate method because static methods are not part of a class instance; they do not logically belong in any class.
If you instead move getOrCreate into a non-static Factory class, you can use some Generics magic to determine the returned type:
public class Entry {
private String name;
}
abstract class AbstractEntryFactory<T extends Entry>
public abstract T getOrCreate(String name);
}
public class EntryFactory extends AbstractEntryFactory<Entry>
#Override
public Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
public class SubEntryFactory extends AbstractEntryFactory<SubEntry>
#Override
public SubEntry getOrCreate(String name) {
// ...
return new SubEntry(name);
}
}
Actually calling the getOrCreate would look different from what it would look like with your code. Instead of this:
Entry myEntry = Entry.getOrCreate("my name");
It would instead look like this:
Entry myEntry = new EntryFactory().getOrCreate("my name");
Or this:
SubEntry myEntry = new SubEntryFactory().getOrCreate("my name");
Assuming you wanted to be able to call Entry.getOrCreate() to create a type of SubEntry, you'll have to pass along some extra information. The reason is that the getOrCreate() method is not inherited by SubEntry, since it is a static method. So if you want to call it the way I mentioned, you'll have to pass along the class name that you want to create. In the code below there are no checks to validate that Class clazz is an Entry or a subtype, but this gives you a start.
import java.lang.reflect.Constructor;
public class TestClass {
public static void main(String[] args) {
Entry entry = (Entry)Entry.getOrCreate("entry", Entry.class);
SubEntry subEntry = (SubEntry)SubEntry.getOrCreate("subEntry", SubEntry.class);
System.out.println("entry class: " + entry.getClass().getName());
System.out.println("subEntry class: " + subEntry.getClass().getName());
}
}
class Entry {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Object getOrCreate(String name, Class clazz) {
// If a constructor is created that takes a String, such as "public Entry(String name)",
// then each sub class will need to implement that method. Instead I used a getter and
// setter for the name attribute.
try {
Entry entry = (Entry)clazz.newInstance();
entry.setName(name);
return entry;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class SubEntry extends Entry {
}
The end result is this output:
entry class: Entry
subEntry class: SubEntry
There are two questions you are asking:
How do I do this?
What is this technique called?
The second one is much more important than the first.
It seems to me like what you are trying to achieve is similar to the concept of cloning (link) or virtual constructor. But you would like this to be a static method, which raises the question as to why? Since a static method is tied to a certain class, not an instance, you should call it through that class in which case you may just as well explicitly be calling new. But having searched for "retrive class in static context" I would say it is not possible to do exactly what you wrote in the question.
If you convert the static method to a normal method, this can be done by using reflection:
class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
public Entry() {
this.name = null;
}
public Entry getOrCreate(String name) {
try {
return getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
return new Entry(name);
}
}
}
class BetterEntry extends Entry {
public BetterEntry(String name) {
super(name);
}
public BetterEntry() {
super();
}
}
You would then be calling the function from an instance, like so:
Entry a = new Entry().getOrCreate("First");
Entry b = new BetterEntry().getOrCreate("Second");
Entry c = b.getOrCreate("Third");
The dynamic types of a, b, c are Entry, BetterEntry and BetterEntry. You could leave out the default constructors, but I added them to make calling getOrCreate feel more like a static method.
If you really want the method to be static, the simplest way would be to just reimplement this function in every subclass.
I've two different type of users, and I've mapped them to two Java classes UserWheel and UserSea and they have a common abstract superclass called User. The data saved for these user types is about the same, but the behavior is different.
Then I created an abstract class called UserCollection with derived classes UserWheelCollection and UserSeaCollection to search for subusers or load a subuser.
Then I've added an abstract method to UserCollection class with signature
public abstract List<User> listAllSubusers()
this is because the implementation will differ. Each User created will be a UserWheel or a UserSea, depending on which method was called, but also all the rest of the implementation is quite different.
Then I want to add a new method to UserCollection with signature public User loadById(int idUser). In this case the implementation would be the same except for the fact that the User returned would be an instance of either UserWheel or UserSea. I'm reluctant in this case to use an abstract method in the base class because of code duplication.
I could check the concrete class of UserCollection with instanceof and create an appropriate subclass, but it doesn't seem object oriented and breaks the open-close principle.
Another idea would be to add an abstract method createNewUser() to UserCollection and concrete implementations in the subclasses to return a new instance, so the base class would just call this createNewUser() method.
Do you think this second path makes sense? Or you would organize things in a different way and how?
UPDATE. The current situation is:
abstract class User
public String getAddress()
public void setAddress()
...
class UserSea extends User
class UserWheel extends User
abstract class UserCollection
protected abstract User createNewUser();
public abstract List<User> listAllSubUsers();
public User loadById(int idUser) {
User newUser = createNewUser();
//populate it
return newUser;
}
class UserSeaCollection
protected User createNewUser() {
return new UserSea();
}
public List<User> listAllSubusers()
class UserWheelCollection
protected User createNewUser() {
return new UserWheel();
}
public List<User> listAllSubusers()
I tried to understand the strategy pattern, as suggested by trashgod, and here is my first attempt:
interface SubuserManagement
List<User> listAllSubUsers();
...
interface UserCrud
void create();
User readById(int idUser);
void update();
void delete();
class UserSeaCollection implements SubUserManagement, UserCrud
private SubUserManagement subuserBehavior = new SubUserManagementSeaImplementation();
private UserCrud userCrudBehavior = new UserCrud();
void create {
subUserBehavior.create();
}
...
class UserWheelCollection implements SubUserManagement, UserCrud
...
class SubUserManagementWheelImplementation implements SubUserManagement
List<User> listAllSubUsers();
class SubUserManagementSeaImplementation implements SubUserManagement
List<User> listAllSubUsers();
class UserCrudImplementation implements UserCrud //only 1 implementation
void create();
User readById(int idUser);
void update();
void delete();
In this first attempt, I've created UserCollectionWheel and UserCollectionSea that don't share anymore a common superclass, but implement the same interfaces. The actual implementation is in external classes.
Now UserCollectionWheel and UserCollectionSea are really the same class, with the only difference of the behavior that I assign to them. Alternatively I could write just one class with setters:
UserCollection userColl = new UserCollection();
userColl.setSubUserBehavior(new SubUserManagementSeaImplementation());
userColl.setCrudBehavior(new UserCrud());
But the initialization would be cumbersome, especially if I had more behavior classes. So what am I doing wrong? How to organize this properly?
UPDATE 2: I wrote a blog post with the design that I've implemented.
Instead of inheriting behavior, consider encapsulating it using interfaces in a strategy pattern. Users would differ in having either of two concrete implementations of an interface ListSubUsersStrategy, interface CreateUserStrategy, etc.
See also the related bridge pattern.
Addendum: In the example below, every user has a concrete strategy for finding sub-users. In particular, listAllSubUsers() invokes the interface method, automatically dispatching to the right concrete implementation. The pattern doesn't relieve you of writing concrete implementations of the interface, but it does de-couple them, ensuring that changing one won't break another.
Console:
A has wheel users.
B has sea users.
C has wheel users.
Code:
import java.util.ArrayList;
import java.util.List;
/** #see http://stackoverflow.com/questions/6006323 */
public class UserMain {
private static final List<User> users = new ArrayList<User>();
public static void main(String[] args) {
users.add(new User("A", new WheelStrategy()));
users.add(new User("B", new SeaStrategy()));
users.add(new User("C", new WheelStrategy()));
for (User user : users) {
user.listAllSubUsers();
}
}
private static class User {
private String name;
private SubUsersStrategy suStrategy;
public User(String name, SubUsersStrategy suStrategy) {
this.name = name;
this.suStrategy = suStrategy;
}
public void listAllSubUsers() {
System.out.print(name + " manages ");
List<User> subUsers = suStrategy.getList();
}
}
private interface SubUsersStrategy {
List<User> getList();
}
private static class WheelStrategy implements SubUsersStrategy {
#Override
public List<User> getList() {
System.out.println("wheel users.");
return null;
}
}
private static class SeaStrategy implements SubUsersStrategy {
#Override
public List<User> getList() {
System.out.println("sea users.");
return null;
}
}
}
FWIW, here's my take on Trashgod's Strategy pattern approach. This is not an answer, just a supporting explanation of Trashgod's answer.
public interface UserStore<T extends User> {
public T create(int id);
public List<T> listAll();
}
public class SeaUserStore implements UserStore<SeaUser> {
public SeaUser create(int id) { return new SeaUser(id); }
public List<SeaUser> listAll() { whatever }
}
// the dry counterpart of 'sea' is either 'land' or 'road', not 'wheel' :)
public class RoadUserStore implements UserStore<RoadUser> {
public RoadUser create(int id) { return new RoadUser(id); }
public List<RoadUser> listAll() { whatever }
}
public class UserCollection<T extends User> {
private UserStore<T> store;
public UserCollection(UserStore<T> store) {
this.store = store;
}
public List<T> listAll() {
return store.listAll();
}
public T getById(int id) {
T user = store.create(id);
// populate
return user;
}
}
This leaves it up to the client to create the UserCollection. You could wrap that; make the UserCollection constructor private, and add:
public class UserCollection<T extends User> {
public static UserCollection<SeaUser> createSeaUserCollection() {
return new UserCollection<SeaUser>(new SeaUserStore());
}
public static UserCollection<RoadUser> createRoadUserCollection() {
return new UserCollection<RoadUser>(new RoadUserStore());
}
}
I could check the concrete class of UserCollection with instanceof and create an appropriate subclass, but it doesn't seem object oriented and breaks the open-close principle.
This would break Liskovs Substitution Principle, which really is a rule to check that one has a sound object hierarchy. The rule says that if a method expects a User as an argument, it should not matter if the user is a CompledUser, DirtyUseror any other user. (Hence you may not have any ifs checking instanceof etc).
Inheritance is all about "is-a" relationships, which basically means that you should be able to take any derived object and pass it to a method which expects the base class. If you can't do that, you are in a lot of trouble. Problems like this is because you have failed with your classes.
Another idea would be to add an abstract method createNewUser() to UserCollection and concrete implementations in the subclasses to return a new instance, so the base class would just call this createNewUser() method
This is a a better approach, since the caller if createNewUser doesn't care about which kind of user it get. All it knows is that it is a user.
The approach is called factory method pattern.