Best way to avoid duplicate code if two classes extending different class - java

I am working on an Android project and i am facing this situation.
I have 2 class :
class A extends B
{
openDoor(){
//impl
}
closeDoor(){
//impl
}
}
class X extends Y{
openDoor(){
//impl
}
closeDoor(){
//impl
}
}
Now if you observe the are two methods common in both the classes openDoor() and closeDoor()
what is the best way to avoid duplicate methods?
My Approach
class ContainingDuplicateMethods{
openDoor(){
//impl
}
closeDoor(){
//impl
}
}
}
Create a object of ContainingDuplicateMethods in both the class and call the methods, which we call it as Strategy Pattern,but is this the best solution? why because in large projects we cannot follow this approach and people say it not GOOD PRACTICE, in that case what approach do i need to follow ?
Please note that class A and X are already extending other classes and also i dont want to use static because - Static members are loaded into memory when the program execution starts and will be in memory until the program is terminated, say my code runs continuously for days or weeks and keeps on creating many number of objects using the static references so there might be a chance that we could run out of memory.

"Favour composition over inheritance" is a useful thing to remember.
Have a Door class with open and close. Include a Door as a member of both A and B.
Voila, job done.
So A.getDoor().close(). B.getDoor().open() etc.
If you need a common interface for both A and B (so you can use either somewhere) then create
interface HasDoor {
Door getDoor();
}
Now A and B can extend any class you like and implement HasDoor. Any class requiring a door can accept a HasDoor (or just directly accept the Door object) and call open, close, etc.
No duplicated code, full flexibility.
If you need your Door to call methods back in A and B then create the Door class as abstract and implement it in A and B as an anonymous inner class. The abstract methods will be called from Door and then you can do whatever processing is needed in A and B when those methods are called.
For example class A becomes:
class A implements HasDoor {
private Door door = new Door() {
#override void notifyDoorChanged(boolean closed) {
// The door is telling us its been opened or closed
}
}
#override
public Door getDoor() {
return door;
}
}
Where door is:
public abstract class Door {
boolean closed;
abstract notifyDoorChanged();
public void close() {
closed = true;
notifyDoorChanged(closed);
}
// etc
}
Note that this is similar to the strategy pattern - but its not quite the same. The Strategy pattern has one master object and then you plug in multiple strategies (i.e. different forms of Door). This has one Door and multiple other objects using the same type of Door, although you could extend it to use the Strategy pattern and have multiple door implementations very easily.

This is the implementation of the answer posted by Tim B.
It is a very flexible approach to go with. It is following the principles of object oriented reuse :
Identify that varies and separate them from what stays the same.
Program to an interface , not an implementation.
Favor object composition over inheritance.
public class Main {
public static void main(String[] args) {
X x = new X();
A a = new A();
x.getDoor().open();
x.getDoor().close();
a.getDoor().open();
a.getDoor().close();
}
}
interface HasDoor {
Door getDoor();
}
interface Door {
public void open();
public void close();
}
class A extends B implements HasDoor {
Door d;
#Override
public Door getDoor() {
Door door = new Door() {
public void open() {
System.out.println("Open A's Door");
}
public void close() {
System.out.println("Close A's Door");
}
};
return door;
}
}
class X extends Y implements HasDoor{
Door d;
#Override
public Door getDoor() {
Door door = new Door() {
public void open() {
System.out.println("Open X's Door");
}
public void close() {
System.out.println("Close X's Door");
}
};
return door;
}
}
class B {}
class Y {}
If you do not want to use HasDoor interface, you can declare constructors inside the class X and class A that initializes the Door instance.
Example ;
class X extends Y {
Door d;
public X() {
d = new Door() {
public void open() {
System.out.println("Open X's Door");
}
public void close() {
System.out.println("Close X's Door");
}
};
}
}

so here your class a and class a has to follow same functions.
that is both classes have same functions.
since the classes already extended another class we can use interface
interface door
{
openDoor(){
}
closeDoor(){
}
}
both class a and x can implement the door interface.
A class can implement any number of interfaces but can extend only one class.
if implementation of class door is same we can do like this
class Door
{
openDoor(){
impl//
}
closeDoor(){
impl//
}
}
class A extends b
{
Door d=new Door();
d.opendoor();
d.closeDorr();
}

Yes, create an abstract class which contains the common code. Have this abstract class implement an interface which contains the necessary methods.
Have both other classes extend the abstract class.

I think you should create an interface with methods openDoor() and closeDoor(). After that inherit classes A and X from this interface and implement methods.
If methods implementation are similar then you can create utility class with static methods.

public interface YourInterface{
public void openDoor();
public void closeDoor();
}
public abstract class YourAbstractClass implements YourInterface{
public abstract void openDoor();
public abstract void closeDoor();
}
public class YourClass extends YourAbstractClass{
#Override
public void openDoor();
public void closeDoor();
}
public class YourSubClass extends YourClass{
//you can just call super methods here
super.openDoor();
super.closeDoor();
}

Related

Issue with multiple Interface implementation in Java8 [duplicate]

Two interfaces with same method names and signatures. But implemented by a single class then how the compiler will identify the which method is for which interface?
Ex:
interface A{
int f();
}
interface B{
int f();
}
class Test implements A, B{
public static void main(String... args) throws Exception{
}
#Override
public int f() { // from which interface A or B
return 0;
}
}
If a type implements two interfaces, and each interface define a method that has identical signature, then in effect there is only one method, and they are not distinguishable. If, say, the two methods have conflicting return types, then it will be a compilation error. This is the general rule of inheritance, method overriding, hiding, and declarations, and applies also to possible conflicts not only between 2 inherited interface methods, but also an interface and a super class method, or even just conflicts due to type erasure of generics.
Compatibility example
Here's an example where you have an interface Gift, which has a present() method (as in, presenting gifts), and also an interface Guest, which also has a present() method (as in, the guest is present and not absent).
Presentable johnny is both a Gift and a Guest.
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { void present(); }
interface Presentable extends Gift, Guest { }
public static void main(String[] args) {
Presentable johnny = new Presentable() {
#Override public void present() {
System.out.println("Heeeereee's Johnny!!!");
}
};
johnny.present(); // "Heeeereee's Johnny!!!"
((Gift) johnny).present(); // "Heeeereee's Johnny!!!"
((Guest) johnny).present(); // "Heeeereee's Johnny!!!"
Gift johnnyAsGift = (Gift) johnny;
johnnyAsGift.present(); // "Heeeereee's Johnny!!!"
Guest johnnyAsGuest = (Guest) johnny;
johnnyAsGuest.present(); // "Heeeereee's Johnny!!!"
}
}
The above snippet compiles and runs.
Note that there is only one #Override necessary!!!. This is because Gift.present() and Guest.present() are "#Override-equivalent" (JLS 8.4.2).
Thus, johnny only has one implementation of present(), and it doesn't matter how you treat johnny, whether as a Gift or as a Guest, there is only one method to invoke.
Incompatibility example
Here's an example where the two inherited methods are NOT #Override-equivalent:
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { boolean present(); }
interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
// "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
// both define present(), but with unrelated return types"
}
This further reiterates that inheriting members from an interface must obey the general rule of member declarations. Here we have Gift and Guest define present() with incompatible return types: one void the other boolean. For the same reason that you can't an void present() and a boolean present() in one type, this example results in a compilation error.
Summary
You can inherit methods that are #Override-equivalent, subject to the usual requirements of method overriding and hiding. Since they ARE #Override-equivalent, effectively there is only one method to implement, and thus there's nothing to distinguish/select from.
The compiler does not have to identify which method is for which interface, because once they are determined to be #Override-equivalent, they're the same method.
Resolving potential incompatibilities may be a tricky task, but that's another issue altogether.
References
JLS 8.4.2 Method Signature
JLS 8.4.8 Inheritance, Overriding, and Hiding
JLS 8.4.8.3 Requirements in Overriding and Hiding
JLS 8.4.8.4 Inheriting Methods with Override-Equivalent Signatures
"It is possible for a class to inherit multiple methods with override-equivalent signatures."
This was marked as a duplicate to this question https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java
You need Java 8 to get a multiple inheritance problem, but it is still not a diamon problem as such.
interface A {
default void hi() { System.out.println("A"); }
}
interface B {
default void hi() { System.out.println("B"); }
}
class AB implements A, B { // won't compile
}
new AB().hi(); // won't compile.
As JB Nizet comments you can fix this my overriding.
class AB implements A, B {
public void hi() { A.super.hi(); }
}
However, you don't have a problem with
interface D extends A { }
interface E extends A { }
interface F extends A {
default void hi() { System.out.println("F"); }
}
class DE implement D, E { }
new DE().hi(); // prints A
class DEF implement D, E, F { }
new DEF().hi(); // prints F as it is closer in the heirarchy than A.
As far as the compiler is concerned, those two methods are identical. There will be one implementation of both.
This isn't a problem if the two methods are effectively identical, in that they should have the same implementation. If they are contractually different (as per the documentation for each interface), you'll be in trouble.
There is nothing to identify. Interfaces only proscribe a method name and signature. If both interfaces have a method of exactly the same name and signature, the implementing class can implement both interface methods with a single concrete method.
However, if the semantic contracts of the two interface method are contradicting, you've pretty much lost; you cannot implement both interfaces in a single class then.
Well if they are both the same it doesn't matter. It implements both of them with a single concrete method per interface method.
As in interface,we are just declaring methods,concrete class which implements these both interfaces understands is that there is only one method(as you described both have same name in return type). so there should not be an issue with it.You will be able to define that method in concrete class.
But when two interface have a method with the same name but different return type and you implement two methods in concrete class:
Please look at below code:
public interface InterfaceA {
public void print();
}
public interface InterfaceB {
public int print();
}
public class ClassAB implements InterfaceA, InterfaceB {
public void print()
{
System.out.println("Inside InterfaceA");
}
public int print()
{
System.out.println("Inside InterfaceB");
return 5;
}
}
when compiler gets method "public void print()" it first looks in InterfaceA and it gets it.But still it gives compile time error that return type is not compatible with method of InterfaceB.
So it goes haywire for compiler.
In this way, you will not be able to implement two interface having a method of same name but different return type.
Try implementing the interface as anonymous.
public class MyClass extends MySuperClass implements MyInterface{
MyInterface myInterface = new MyInterface(){
/* Overrided method from interface */
#override
public void method1(){
}
};
/* Overrided method from superclass*/
#override
public void method1(){
}
}
The following two approaches can also be taken to implement both the duplicate methods and avoid ambiguity -
APPROACH 1:
App.java -
public class App {
public static void main(String[] args) {
TestInterface1 testInterface1 = new TestInterface1();
TestInterface2 testInterface2 = new TestInterface2();
testInterface1.draw();
testInterface2.draw();
}
}
TestInterface1.java -
public class TestInterface1 implements Circle {
}
TestInterface2.java -
public class TestInterface2 implements Rectangle {
}
Circle.java -
public interface Circle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java -
public interface Rectangle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java -
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle
APPROACH 2:
App.java -
public class App {
public static void main(String[] args) {
Circle circle = new Circle() {
};
Rectangle rectangle = new Rectangle() {
};
circle.draw();
rectangle.draw();
}
}
Circle.java -
public interface Circle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java -
public interface Rectangle extends Drawable {
#Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java -
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle

method implemented in abstract class, but appears in interface

I'm learning abstract classes vs interfaces at the moment and trying to figure out situations where to use one over the other. I'm having trouble figuring out this example at the moment:
public interface Face {
public void test();
}
public abstract class Tract {
public void test() {
System.out.println("over here");
}
}
public class Thing extends Tract implements Face {
public void test() {
// what should print out?
}
}
Here, the test() function is implemented in the abstract class. If you don't implement it in the subclass, would it call the abstract class' method and print out "over here"? Does the interface accept implementations from an ancestor class or do you have to implement it in the subclass, therefore overriding the abstract class implementation?
All the interface cares about is that the class has implemented a method called test() that returns void. It does not matter whether the method is implemented in the class directly or in any ancestor (parent) class.
In your case, the Thing class has inherited its definition of test() from Tract, and therefore implements the Face interface without you having to provide a definition explicitly.
In the class "Tract" you have given an implementation for the method coming from the interface. Also you override it in "Thing" class so when calling this method on a Thing instance then this version(Thing version) is going to be called.
All java methods are virtual.
lets consider little bit modified code,
I hope, you will get the idea:
public interface Face {
public void test();
}
public abstract class Tract {
public void test() {
System.out.println("Tract here");
}
}
public class Thing extends Tract implements Face {
public void test() {
System.out.println("Thing here");
}
}
public class Thing2 extends Tract implements Face {
}
lets go to output:
Tract tr = new Tract();
tr.test();
will not compile because you can't instantiate abstract class.
Thing th = new Thing();
th.test();
will print "Thing here"
Thing2 th2 = new Thing2();
th2.test();
will print "Tract here",
because you not overwritten the test() method in abstract class.
Main idea of this approach - you can abstract implementation in the future use
class C {
void print(Face face) {
face.test();
}
}
new C(new Thing()).print();
will print "Thing here";
new C(new Thing2()).print();
will print "Tract here";
You can hide different implementations
But this is not main idea of abstract classes.
main idea abstract classes are:
public interface Face {
public void test();
}
public abstract class Abstract {
abstract public void test();
}
public class Thing1 extends Abstract implements Face {
public void test() {
System.out.println("Thing1 here");
}
}
public class Thing2 extends Abstract implements Face {
public void test() {
System.out.println("Thing2 here");
}
}
main idea - you can declare method without implementation
new C(new Thing1()).print();
will print "Thing1 here";
new C(new Thing2()).print();
will print "Thing2 here";
main idea - you declare the method in abstract class, that you MUST override to compile code.
I hope, this is enough explained answer.

Is forcing a constructor signature a valid reason to use an abstract class rather than an interface?

For a project, I have written the following interface:
public interface IManipulation {
void applyManipulation (double value);
}
Since I would like to force all implementing classes to use a certain constructor signature, I have been considering to change the interface into something like the following abstract class:
(edit: I forgot that it's not possible to have an abstract constructor, so I changed the "solution" below a bit)
public abstract class Manipulation {
private Signal signal;
public Manipulation (Signal signal) {
this.signal = signal;
}
public abstract void applyManipulation (double value);
protected Signal getSignal () {
return signal;
}
}
The reason for wanting to force this constructor is because every implentation should have an instance of Signal available. (and it should not be possible to reassign this signal)
Is this a valid reason to replace the interface with an abstract class (and live with the limitations that come with it), or are there any other potential solutions?
instead of an abstract class you should use an init method for that purpose.
public interface MyInterface{
public void init(YourParam p);
//... other methods
}
in the init you check, if the class is allready initialised if yes, just return.
So you have still an interface and can extend from other classes.
Instead of the constructor you will call the init method for your initialization
EDIT:
public interface IManipulation {
void init(Signal s);
void applyManipulation (double value);
}
You should use abstract classes only, if you have implementation details in it, which are shared by all subclasses. For Method signatures use interfaces
You can make empty constructor private in the abstract class:
abstract class AbstractManipulation {
private final Integer signal;
private AbstractManipulation() {
signal = null;
}
public AbstractManipulation (Integer signal) {
this.signal = signal;
}
}
class Manipulation extends AbstractManipulation {
public Manipulation(Integer signal) {
super(signal);
}
// Cannot redeclare
//public Manipulation() {
//}
}
Then:
public static void main(String[] args) {
// Will not work
//Manipulation m = new Manipulation();
// This one will
Manipulation m = new Manipulation(1);
}
You should not choose for technical reasons but rather logical, ie an abstract class is used when you have a realtion with the sub-classes like for example person: student, teacher. An interface is used when you want to impose a service contract for classes that may not have a relationship between them.

What kind of relationship does an interface have with it implementing class?

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.

Techniques to expose multiple Interfaces (via static creation methods)

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");

Categories