I am currently working on a project where I am attempting to hide as much detail about a hierarchy I have created as possible. I want to do this to minimize the amount of information the user needs to know about objects (and to control what they can do to the state of the object). In addition, I'm using the pattern to limit what kinds of objects the application can make, and limit it to creation from the factory.
The main issue I am having, however, is that there are a few different kinds of interfaces I would like to expose. Each interface is has additional functionality that I don't believe should be shared, and I would like to keep these interfaces separated. Finally, I don't know what new interfaces may come in the future, but I'd like to try and be ready for them.
Weapon:
public interface Weapon extends GameObject {
Number attack();
boolean addWeaponAttribute(WeaponAttribute attribute);
}
Firearm:
public interface Firearm extends Weapon {
void reload(Number rounds);
}
My question is what would be the best way to have the factory produce objects with different interfaces? Here's what I am thinking "the best would be":
The most clear to the user (it's obvious what they're asking for and what they're getting back)
The best for future expansion (I am uncertain what new interfaces I will be adding to this system).
Here's what I have been thinking so far:
Create properly named methods for each interface
public static Firearm getFirearm(String firearmName) {
...
}
public static Weapon getWeapon(String weaponName) {
...
}
Do the above, but produce the factories in separately named classes
public class WeaponFactory {
public static Weapon getWeapon(String weaponName) {
...
}
}
public class FirearmFactory {
public static Firearm getFirearm(String firearmName) {
...
}
}
Something completely different
I'm open to suggestions, and changes. This is a flexible project, so I can change as much as I want to (in terms of this portion of the project) to make a better result.
Also - As a side note, I was uncertain if this question was too open-ended or not for SO. If I made a mistake posting here, let me know and I'll move my question elsewhere.
What I can suggest is to make the interfaces as concise as possible and move other unrelated methods elsewhere. you might consider doing this for example:
public interface Weapon extends GameObject {
Number attack();
}
public interface Modifiable extends GameObject {
boolean addWeaponAttribute(WeaponAttribute attribute);
}
public class ActualWeapon implements Weapon, Modifiable {
...
}
Then you can create different factories to generate your concrete objects, as you already mentioned:
public class WeaponFactory {
public static Weapon getWeapon(String weaponName) {
...
}
}
or
public class GenericFactory<T extends GameObject> {
public T createGameObject(Object... properties) {
...
}
}
public class WeaponFactory extends GenericFactory<ActualWeapon> {
public ActualWeapon createGameObject(Object... properties) {
...
}
}
I think you can't add static methods to interfaces. I wouldn't recommend it if you even could.
maybe just use the factory method design pattern like
interface GameObject {}
class WeaponAttribute {}
interface Weapon extends GameObject {
Number attack();
boolean addWeaponAttribute(WeaponAttribute attribute);
}
interface Firearm extends Weapon {
void reload(Number rounds);
}
class WeaponBaseClass implements Weapon {
WeaponBaseClass(WeaponName weaponName) {
this.weaponName=weaponName;
}
#Override public Number attack() {
return null;
}
#Override public boolean addWeaponAttribute(WeaponAttribute attribute) {
return false;
}
public String toString() {
return weaponName.toString();
}
final WeaponName weaponName;
}
class FirearmBaseClass extends WeaponBaseClass implements Firearm {
public FirearmBaseClass(WeaponName weaponName) {
super(weaponName);
}
#Override public void reload(Number rounds) {}
}
enum WeaponName {
knife, sword, colt45, glock19, glock19WithLaser;
}
class WeaponCreator {
Weapon create(WeaponName weaponName) {
switch (weaponName) {
case knife:
case sword:
return new WeaponBaseClass(weaponName);
case colt45:
case glock19:
return new FirearmBaseClass(weaponName);
default:
return new WeaponBaseClass(weaponName);
}
}
}
class FancyWeaponCreator extends WeaponCreator {
Weapon create(WeaponName weaponName) {
Weapon weapon = null;
switch (weaponName) {
case glock19WithLaser:
weapon = super.create(WeaponName.glock19);
// whatever it needs
return weapon;
default:
return new WeaponBaseClass(weaponName);
}
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new WeaponCreator().create(WeaponName.knife));
System.out.println(new WeaponCreator().create(WeaponName.colt45));
System.out.println(new FancyWeaponCreator().create(WeaponName.glock19WithLaser));
}
}
What about a factory of factories? Each factory would implement ifactory. Ifacorty would require a method Instantiate(string type) and return your subclassed weapon instance.
Using generics, you might only need one factory method like:
public <T> T getObject(java.lang.Class<T> responseType, String name)
Then the user would call:
Weapon weapon = factory.getObject(Weapon.class, "my weapon");
Related
I have 2 classes Workflow1.java and Workflow2.java. At a class Selection.java I want to be able to choose between instantiating one of the 2 classes as a static member however I cannot implement the factory pattern as Workflow1 and Workflow2 cannot be subclasses since their methods are not the same. Although they achieve the same end result they do so by doing entirely different operations. Is there a design pattern for this scenario?
Example: If the classes were WalkHelper.java and DriveHelper.java, the methods you need in each are entirely different but what you are trying to achieve is the same - reach a destination. I haven't created walk() and drive() as methods as WalkHelper.java has existed in our code base and I'm adding DriveHelper.java to it.
It sounds like you can still use a Factory pattern but you may have to use an Adaptor to make them equal... Without knowing more, it's a pretty difficult question to answer.
interface IFactory {
void run();
String getResult();
}
class Workflow1Adapter implements IFactory {
Workflow1 wf1 = new Workflow1();
public void run() {
wf1.doSomething();
}
public String getResult() {
wf1.doAnother();
}
}
class Workflow2Adapter implements IFactory {
Workflow2 wf2 = new Workflow2();
public void run() {
wf2.doThatThing();
}
public String getResult() {
wf2.doReturn();
}
}
class Workflow1 {
public void doSomething() {}
public String doAnother() {}
}
class Workflow2 {
public void doThatThing() {}
public String doReturn() {}
}
I'm working with students in my Java class on a simple Zork-like environment in which the player goes from location to location encountering items. The items should have dynamic behaviors, so that a book is readable until you burn it, or a duck can fly until it flies too long and tires out. And so on.
The students and I have grokked the basic Strategy pattern (I'm adapting from Head First Design Patterns, and leaving out boilerplate):
public class Duck {
String name;
Int health;
FlyBehavior flyBehavior;
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
}
}
public interface FlyBehavior {
public void fly();
}
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
}
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
}
Sparing the details of the main method, this lets us switch different flying behaviors into our Duck. This is easy because it returns a void and prints to sysout.
But what if we need the behavior to interact with the state of the Duck? Let's say that:
When the duck becomes too tired to fly, its name changes to "Exhausted Duck." Other behaviors can change its name, too.
When the duck is attacked (gonna happen), its health goes down. When its health is too low, its flyBehavior switches out to the TooTiredToFly behavior.
But I'm assuming that dynamic behaviors, at least in this pattern, have no access to the state of the object they're in.
Is there a general strategy for creating dynamic behaviors that interact with the state of the object they're in? I would like to teach something comprehensible, so put yourself in the mind of intermediate-level high school programmers.
Based on my comment above, something along these lines...
// Creating an interface for flyable things e.g. Duck, Airplane, etc.
// You don't have to do this. You could just pass your Duck
// object instead and call its methods directly.
public interface Flyable {
void performFly();
}
public class Duck implements Flyable {
// All your Duck stuff as above in here.
}
public abstract class FlyBehavior {
private Flyable parent;
public FlyBehavior(Flyable parent) {
this.parent = parent;
}
public abstract void fly();
protected Flyable getParent() {
return this.parent;
}
}
public class FlyGracefullyBehavior extends FlyBehavior {
public FlyGracefullyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
public class TooTiredToFlyBehavior extends FlyBehavior {
public TooTiredToFlyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
Or, you could simply pass parent state in the fly method of your FlyBehavior classes i.e. behavior.fly(state); It's up to you :)
Here's a basic example of using the Strategy pattern as you have described. I'm trying to keep it as simple as possible so some best practices were ignored (e.g. declaring constants) so you can focus on the Strategy design and not be overwhelmed with information.
public interface Animal
{
public String getName();
public void attacked(int health);
}
public interface Bird extends Animal
{
public void fly();
}
public class Duck implements Bird
{
private Int health = 100;
private DuckBehavior state = new HealthyDuck();
public getName()
{
return state.getName();
}
public void fly()
{
state.fly();
}
public void attacked(int hitpoints)
{
health = health - hitpoints;
if (health < 50) {
state = new HurtDuck();
} else if (health < 0) {
state = new DeadDuck();
}
}
}
interface DuckBehavior
{
public getName();
public void fly();
}
public class HealthyDuck implements DuckBehavior
{
public getName()
{
return "Healthy Duck";
}
public void fly()
{
System.out.println("I fly so gracefully!");
}
}
public class HurtDuck implements DuckBehavior
{
public getName()
{
return "Hurt Duck";
}
public void fly()
{
System.out.println("I'm too tired to fly.");
}
}
public class DeadDuck implements DuckBehavior
{
public getName()
{
return "Dead Duck";
}
public void fly()
{
System.out.println("I'm too dead to fly.");
}
}
Lets add a new interface in the design as below
Flyable.java
public interface Flyable{
public void modifyTargetName(String newName);
}
Lets Modify the FlyBehavior.java and its implementation classes. Lets define a method public void setFlyableTarget( Flyable target ) in it.
FlyBehavior.java
public interface FlyBehavior {
public void fly();
public void setFlyableTarget( Flyable target );
}
FlyGracefully.java
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("GraceFul Flyer");
}
}
TooTiredToFly.java
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("TiredFlyer");
}
}
Duck.java let it implement Flyable.java
public class Duck implements Flyable{
String name;
Int health;
FlyBehavior flyBehavior;
public void modifyTargetName(String newName){
this.name = newName;
}
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
f.setFlyableTarget(this);
}
}
The good thing here is we do not expose concrete implementation and hence code remains unit testable and good for adaptation to changes. It adheres to the DIP : Dependency Inversion Principle as well.
One general point I'd like to make: Don't modify internal behavior of an object, it's rude. I mean, there should not be a setFlyBehavior() method, that is an internal attribute of the Duck.
Also, think about who is responsible for what. Once a Duck is constructed, you can ask a Duck to fly, and you can make the Duck take Damage. How those things change the Duck is none of our business at that point.
On a more practical note, this is how that might look:
public interface Being {
boolean isDamaged();
}
public interface FlyingBehavior {
void fly();
}
public class GracefulFlyingBehavior implements FlyingBehavior {
...
}
public class TiredFlyingBehavior implements FlyingBehavior {
...
}
public class BirdFlyingBehavior implements FlyingBehavior {
private int tiredness;
...
public BirdFlyingBehavior(Being bird) {
...
}
#Override
public void fly() {
if (bird.isDamaged() || isTired()) {
tiredFlying.fly();
} else {
gracefulFlying.fly();
tiredness++; // Or whatever...
}
}
}
The point is, that the behavior itself should be responsible for deciding whether the flying can take place. It is after all the "strategy" for flying, so this logic needs to be there.
Then you can construct a duck something like this:
public Duck(String name, ... ) {
...
this.flyBehavior = new BirdFlyingBehavior(this);
}
or something similar. The point here is that once that strategy is set, it should stay internal to the Duck, there should be no way to modify that directly anymore.
Of course there might be additional features (you might want to move "tiredness" to the general "health" of a being), but the concepts should not change. Objects should hide their internal state, this requires "responsibilities" to be at the right place.
A subclass has a relationship that is described as IS-A with it base class, but a base class does not share this kind of relationship with it subclass. I was wandering what kind of relationship an interface have with it implementing class since an object of that class can be passed to interface object and the interface object can only access methods defined it concrete Interface.
public class main {
public static void main(String[]args){
Nigeria ng = new Nigeria(){};
//Interface object can accept Nigerias object which is not posible in Inheritance
Continent continent = ng;
//prints Country is in Africa
continent.Africa();
//continent.language(); will not compile language is not in the interface
//Print Democratic thought this should print Undefined since it is inialied with default.
continent.Goverment();
}
}
interface Continent{
public void Africa();
default void Goverment(){
System.out.println("Undefined");
}
}
class Nigeria implements Continent{
#Override
public void Africa(){
System.out.println("Country is in Africa");
}
public void language(){
System.out.println("Official Language is English");
}
public void Goverment(){
System.out.println("Democratic");
}
}
If you are looking for English-language analogues, an Interface is not an "Is a..." nor "Has a..." relationship, but more an "Is...".
An Interface is not about the class that uses it.
It's about the consumer that asks for it.
If you wanted to see it as anything, you could see it as an adjective.
"He is Responsible".
Well, what does he do?
He finishes tasks; he takes ownership of his mistakes; he makes them right.
Is he a pilot, is he a surgeon, is he a doctor?
Is he a child, a father, a greatGrandfather?
Do you care?
I need a responsible person, to help me do this job.
Does ResponsiblePerson inherit from PoliceOfficer? Does Lawyer inherit from ResponsiblePerson, because I'm sure there can be irresponsible lawyers.
class Lawyer extends Person { }
class ResponsibleLawyer extends Lawyer implements ResponsibleEntity { }
class NeedyPerson extends Person {
public void acceptHelp (ResponsibleEntity somebody) {
try {
somebody.attemptTask( someTask );
} catch (TaskCompletionError err) {
somebody.takeOwnership(err);
somebody.fixMistake(err);
}
}
}
Can corporations be Responsible too?
Perhaps we don't see it too often, but it's theoretically possible:
class LawFirm extends CorporateEntity { }
class BetterLawFirm extends LawFirm implements ResponsibleEntity { }
Can somebody be a responsible corporate body? Well, so long as that corporate body does all of the same things that the responsible person would otherwise do, sure.
In another example, you might have a Switchable interface.
Looking at that name, you could surmise that the thing you're being given has a switch which can be poked.
So what methods might it have?
on( )
off( )
toggle( )
isOn( )
sounds like a useful set to have.
What benefit is there to having an interface like this?
Well, now I know that I can deal with a switch, and its lineage doesn't matter.
If all I want is a class which takes a switch and does something with it, why do I need to create dozens of classes, just to accept my dozens of things with switches?
Or override methods into the dirt to do the same.
class SwitchThrower {
public void throwSwitch (CoffeeMaker coffeeMaker) { coffeeMaker.on(); }
public void throwSwitch (LightSwitch lightSwitch) { lightSwitch.on(); }
public void throwSwitch (GhostTrap ghostTrap) { ghostTrap.on(); }
public void throwSwitch (TheHeat theHeat) { theHeat.on(); }
public void throwSwitch (CarIgnition ignition) { ignition.on(); }
}
...
why not just:
class SwitchThrower {
public void throwSwitch (Switchable switch) { switch.on(); }
}
class LightSwitch implements Switchable {
private boolean currentlyOn;
public LightSwitch (boolean initiallyOn) {
currentlyOn = initiallyOn;
}
public LightSwitch () {
currentlyOn = false;
}
public boolean on () {
currentlyOn = true;
return currentlyOn;
}
public boolean off () {
currentlyOn = false;
return currentlyOn;
}
public boolean toggle (boolean forceOn) {
boolean state;
if (forceOn == true) {
state = on();
} else {
state = off();
}
return state;
}
public boolean toggle () {
boolean state;
if (isOn() == true) {
state = off();
} else {
state = on();
}
return state;
}
public boolean isOn () {
return currentlyOn;
}
}
...et cetera
As you can see, aside from describing a basic feature-set of the implementer, interfaces are not about the class at all, but rather the consumer.
An even more awesome implementation of this, in different languages, is _Traits_.
Traits are typically like Interfaces, but they have default behaviour associated with them.
Looking at my Switchable and my LightSwitch, you could imagine that practically all classes with this switch would have the same methods, with the same method behaviour...
...so why would I rewrite all of those methods over again, if I'm already going through the trouble of defining the signature in the interface?
Why couldn't I just add default behaviour in there, and have it apply to the implementer, unless a method is overridden?
Well, that's what Traits / Mix-Ins allow.
The relationship is only the "contract" that the class is getting to implement the methods the interface is offering.
That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.
Let me start with an example.
Say I have an abstract Vehicle class.
public abstract class Vehicle {
public Vehicle() {}
public abstract void ride();
}
And classes Car and Bicycle that inherit from this abstract class.
public class Car extends Vehicle {
public Car() {}
#Override
public void ride() {
System.out.println("Riding the car.");
}
}
public class Bicycle extends Vehicle {
public Bicycle() {}
#Override
public void ride() {
System.out.println("Riding the bicycle.");
}
}
When I apply the ride() method to an object of type Vehicle whose actual type can only be determined at runtime, the JVM will apply the correct version of ride().
That is, in a curried method call of the sort v.ride(), polymorphism works the expected way.
But what if I have an external implementation in form of a method that only accepts a subtype of Vehicle as an argument? So, what if I have repair(Bicycle b) and repair(Car c) methods? The uncurried polymorphic method call repair(v) won't work.
Example:
import java.util.ArrayList;
import java.util.List;
public class Main {
private static void playWithVehicle() {
List<Vehicle> garage = new ArrayList<Vehicle>();
garage.add(new Car());
garage.add(new Car());
garage.add(new Bicycle());
garage.forEach((v) -> v.ride()); // Works.
garage.forEach((v) -> {
/* This would be nice to have.
repair(v.castToRuntimeType());
*/
// This is an ugly solution, but the obvious way I can think of.
switch (v.getClass().getName()) {
case "Bicycle":
repair((Bicycle) v);
break;
case "Car":
repair((Car) v);
break;
default:
break;
}
});
}
private static void repair(Bicycle b) {
System.out.println("Repairing the bicycle.");
}
private static void repair(Car c) {
System.out.println("Repairing the car.");
}
public static void main(String[] args) {
playWithVehicle();
}
}
I have to check for the class name and downcast. Is there a better solution to this?
Edit: My actual purpose is that I'm traversing an abstract syntax tree and I happened to notice that I want double dispatch.
Ast is an abstract class from which actual AST nodes like Assign, MethodCall, or ReturnStmt inherit. body is a polymorphic list of Asts.
Code snippet:
List<Ast> body;
body.parallelStream().forEach((ast) -> {
// This one won't work.
visit(ast);
// This one will work.
if (ast instanceof Assign) {
visit((Assign) ast);
} else if (ast instance of MethodCall) {
visit((MethodCall) ast);
} else if (ast instance of ReturnStmt) {
visit((ReturnStmt) ast);
}
// etc. for other AST nodes
});
private void visit(Assign ast) {
}
private void visit(MethodCall ast) {
}
private void visit(ReturnStmt ast) {
}
My only possibilities of achieving double dispatch is either checking the class and downcasting or properly implementing the visitor pattern, right?
Answer: There is no multiple dispatch in Java and it can be simulated by instanceof or by the visitor pattern.
See here:
Java method overloading + double dispatch
See also here: https://en.wikipedia.org/wiki/Multiple_dispatch#Examples_of_emulating_multiple_dispatch
On a sidenote, exactly this is possible in C# with dynamic calls: How to build double dispatch using extensions
And this is also possible in the many languages that are compiled to JVM bytecode, e.g. Groovy was mentioned.
Consider the simple example below of implementing a method in an Enum. One problem with this method is that, when you have a lot of enum instances, you visually can no longer see them all at once, as a list. That is, if we had many toys, I would like to see "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", together, in one long list, and then after that list I could implement any needed methods, e.g. methods that are abstract in the enum itself.
Is there any way to do this? Or do you have to implement the methods when you declare the individual enum instances, as in the example below?
public enum Toy {
DOLL() {
#Override public void execute() {
System.out.println("I'm a doll.");
}
},
SOLDIER() {
#Override public void execute() {
System.out.println("I'm a soldier.");
}
};
//abstract method
public abstract void execute();
}
One way that comes to mind is to leave the implementation of the abstract methods to separate implementation classes, something like:
interface ToyBehaviour {
void execute();
}
public enum Toy {
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
}
class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
This setup would allow you to create behaviour classes in separate files in the case that your implementation has enough complexity to warrant separation.
In the case that the implementation is simple enough to include it into the one enum class, you can put the interface and behaviour classes as children of the enum class:
public enum Toy {
// enum values
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
// behaviour interface
interface ToyBehaviour {
void execute();
}
// behaviour implementation (sub)classes
static class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
// etc ...
}
I would probably opt for the first implementation myself, unless the hierarchy of implementation classes is very trivial.
If you want more compact enum declarations, the only ways I can think of to do it are :
if you can construct your methods out of initializer variables:
public enum Toy {
DOLL("doll"),SOLDIER("soldier");
private Toy(String name){ this.name=name;}
public void execute(){ System.out.println("I'm a "+name );}
}
or, slightly more complicated, kind of the same with functions, if the behavior is more complex -
abstract class SomeToyMethod {
abstract void execute();
public SomeToyMethod DOLL_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a doll");})
public SomeToyMethod SOLDIER_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a soldier");})
public enum Toy {
DOLL(SomeToyMethod,DOLL_METHOD),SOLDIER(SomeToyMethod.SOLDIER_METHOD);
private Toy(SomeToyMethod method){ this.method=method;}
public void execute(){ method.execute();}
}
You could try something like:
public enum Toy {
DOLL,
SOLDIER,
ANOTHER_TOY;
public static void execute(Toy toy) {
switch(toy) {
case DOLL:
System.out.println("I'm a doll.");
break;
case SOLDIER:
System.out.println("I'm a soldier.");
break;
case ANOTHER_TOY:
System.out.println("I'm another toy.");
break;
}
}
}
Not very pretty but it keeps your enum declarations together.