I am experience some problems in understanding how the OO pattern works, My lecturer gave me the following question but I cannot solve it after thinking whole day
Scenario for my problems.
There is a class named "ShapeManager" which manages the Shape object. A class named "Shape" has two subclasses named "Circle" and "Rectangle"
The implementation of Shape class as follow
abstract public class Shape {
private String id;
private double length;
public Shape() {
}
public Shape(String id , double length) {
this.id = id;
this.length = length;
}
public void setID(String id) {
this.id = id;
}
public String getID() {
return id;
}
public void setLength(double length) {
this.length = length;
}
public double getLength() {
return length;
}
public abstract String getDetails();
}
The subclass Square as follow
public class Square extends Shape{
public Square() {
super();
}
public Square(String id , double side) {
super(id, side);
}
#Override
public String getDetails() {
return "Square => Id : "+getID() +", Side : "+ getLength() + ",Area : "+(getLength() * getLength());
}
}
The subclass Circle as follow
public class Circle extends Shape{
public Circle(){
super();
}
public Circle (String id, double radius) {
super(id, radius);
}
#Override
public String details() {
return "Circle => Id : "+getID() + ", Radius : "+ getLength() + ",Area: "+(3.14*(getLength() * getLength()));
}
}
The ShapeManager class as follow, this is not a completed class
public class ShapeManager {
public Shape createShape() {
}
public void updateLength(String id ){
}
public void deleteShape(String id) {
}
public void listShapes() {
}
}
ShapeManager have an association with Shape
ShapeManager --1------0..*--> Shape
The design of this package (All the classes above) can not be changed, implementation must be following OCP (Open-Closed Principle).
My question is: How am I suppose to complete createShape method? Without parameter, it is seemingly impossible to create an object either a Rectangle or Circle.
ShapeManager cannot create a shape if not knowing what this shape is (Square, Circle or something else). And it really doesn't know because you say the method createShare has no parameters. Either you misunderstood the question or the lecturer didn't explain it well. You should ask him/her for clarifications. If you look at the libraries of Java or any other OO language, I am pretty sure you won't find such scenario and implementation pattern as the one you gave in your example.
#croraf
You should find some other reading I think e.g. the classic book http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612. The main idea of a factory is that it returns something whose type the caller doesn't know, and doesn't care about. For example, if you have a method createSocket() in some SocketFactory, this method is usually defined to return an interface or an abstract class Socket. But actually it returns new SocketImpl1() and new SocketImpl2() which are concrete classes. What the factory returns may depend on many things - a system property, the underlying OS, anything you can think of. The main idea is that the factory centralizes the creation of Socket objects at one single place. This way, if you need to make a change, you can make it just in the factory. I think this book also has some decent Java counterparts too, you may look around. Other free good sources are referenced here.
Real world examples of Factory Method pattern
I think you should have something like this, similar to how BorderFactory from java API works.
public class ShapeManager {
public Shape createCircle() {
...
return Circle;
}
public Shape createSquare() {
....
return Square;
}
...
public void updateLength(String id ){
}
public void deleteShape(String id) {
}
public void listShapes() {
}
}
You can't create shape without knowing type which shape would You like to create. You can define enumeration for types and pass the type value to the createShape(). And there You can switch between types and create the concrette shape You want.
For me, Its classic Factory pattern.
public class ShapeFactory {
public abstract Shape getShape(int shapeId);
}
public interface Const {
public static final int SHAPE_CIRCLE =1;
public static final int SHAPE_SQUARE =2;
}
public class SimpleShapeFactory extends ShapeFactory throws BadShapeException {
public Shape getShape(int shapeTypeId){
Shape shape = null;
if(shapeTypeId == Const.SHAPE_CIRCLE) {
//in future can reuse or cache objects.
shape = new Circle();
}
else if(shapeTypeId == Const.SHAPE_SQUARE) {
//in future can reuse or cache objects
shape = new Square();
}
else throw new BadShapeException("ShapeTypeId="+ shapeTypeId);
return shape;
}
}
Calling:
ShapeFactory factory = new SimpleShapeFactory();
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
Shape s = factory.getShape(1);
s.getDetails(); // circle details called
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
s = factory.getShape(2);
s.getDetails(); //Square details called
References:
The Open Close Principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code. The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.
Related
I am relatively new to Java and programming, so I apologize if this question seems stupid. I am creating a battle-game for a Java programming class -- I have a Hero class with some basic methods and a subclass Paladin that extends Hero but with its own unique methods added in. I want to have a Battleground object that passes in ANY Hero class but then check which specific subclass was passed in. How do I determine which of the Hero subclasses were passed in?
public class Hero {
private String name;
private int hitPoints;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
}
public String getName() { return this.name; }
public int getHitPoints() { return this.hitPoints; }
public void takeDamage(int amount) { this.hitPoints -= amount; }
}
And here is the Paladin Class
public class Paladin extends Hero {
public Hero (String name, int hitPoints) {
super(name, hitPoints);
}
public void heal(int amount) {
this.hitPoints += amount;
}
}
So in the battleground class, I have a method that attempts (incorrectly) to check if the hero passed in is a Paladin. How would I go about doing this? The if statement is a placeholder psuedo-code just to clarify what I mean.
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
Thinking in terms of what your classes are actually modelling, it doesn't make much sense for a battleground to know that a Paladin heals themselves at the start of a round, nor for the battleground to be responsible for making sure the Paladin heals themselves.
A more sensible design would be for the game to inform the hero that the round has started, and let the particular Hero subclass control what that kind of hero does when the round starts. For example:
public class Hero {
// ...
public void onRoundStart() {
// do nothing
}
}
public class Paladin extends Hero {
// ...
#Override
public void onRoundStart() {
// your heal method takes an int as its argument
heal(10);
}
}
public class Battleground {
// ...
public void startRound() {
// let the particular Hero subclass control what happens
player.onRoundStart();
// ...
}
}
This way you don't need any if statements or instanceof checks, but also the code defining a Paladin's behaviour is in the Paladin class where it sensibly belongs. If you want to change the rules for Paladins later, it will be easier to know which class you need to edit.
This kind of refactoring is called "replace conditional with polymorphism".
Using Instanceof is Considered a Code Smell Sometimes
Using instanceof can be considered to be a code smell - which means a bad practice.
There is an alternative for you to consider.
Add the heal() method to the Hero class, but leave the implementation blank.
Put only an implementation in the Paladin class. Then, even though heal() will be called on all players, it will only do something inside Paladins.
However... if you still need to detect the class type...
Ways to Detect the class
There are multiple ways to differentiate between classes.
Instance of is one.
Another is having different constructors.
A third is having an ENUM or String field called EntityType.
In your case, I think instanceof or using a special field make the most sense.
Instanceof
if(player instanceof Paladin)
Using a Special Field
Quick Example Hero
public class Hero {
private String name;
private int hitPoints;
private int HeroType;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
this.heroType = BASIC_HERO;
}
public static int BASIC_HERO = 0;
public static int PALADIN_HERO = 1;
...
}
Quick Example Paladin
public class Paladin extends Hero {
public Paladin(String name, int hitPoints) {
super(name, hitPoints);
this.heroType = PALADIN_HERO;
}
}
Detecting the Type
You would have a method in both classes called getHeroType().
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
If you want, you can use to check the class of the object:
if (player instanceof Paladin)
No question, this will work. If you don't have a lot of "special" behaviour and a limited small amount of cases, that can be a reasonable solution. But assuming that your game will end up with a lot of special handling for each subclass of Hero and probably not only in the startRound() method of your Battlefield class, your code will someday be cluttered with these instanceof checks. Same applies, if you use a specific type field within the Hero class.
In that case a better solution might be to relocate the logic into special classes and try to avoid type checks if possible or at least have a well defined place for them, if necessary.
Update: removed faulty demo implementation
You can always do player.getClass to get actuall class. As for if statements you can use instanceof operator.
So
if (player instanceof Paladin) {
((Paladin)player).heal();
}
Lets say I had a simple inheritance structure like so:
class Shape {
int id;
}
class Circle extends Shape {
int radius;
}
class Square extends Shape {
int length;
}
class ToyBox {
List<Shape> shapes;
}
These objects cannot be augmented in any way (no adding methods/fields/accessors.change the file in any way) and should be treated as immutable/final. I have to return each of these shape objects to another part of the system I am working within with some extra information to go alongside each item. For example:
class extended Shape {
int id;
}
class ExtendedCircle extends ExtendedShape {
public Circle circle;
public Blah circleStuff;
public ExtendedCircle(Circle circle) {...}
}
class ExtendedSquare extends ExtendedShape {
public Square square;
public Blah squareStuff;
public ExtendedSquare(Square square) {...}
}
The only way I can think of accomplishing this task given a ToyBox of shapes is to iterate through the shapes list, do an instance of check and do a cast to circle, square etc. to then construct each of the corresponding "Extended" objects. This makes me a little uncomfortable so i am wondering if there is another way to design such a system?
If you need to avoid casting and using instanceof operator you probably would like to consider using Vistor design pattern. Applying it to your example if might looks as following:
class Shape {
int id;
public void visitingShape(ToyBox box) {
box.visitingShape(this);
}
}
class Circle extends Shape {
int radius;
public void visitingShape(ToyBox box) {
box.visitingCircle(this);
}
}
class Square extends Shape {
int length;
public void visitingShape(ToyBox box) {
box.visitingSquare(this);
}
}
class ToyBox {
List<Shape> shapes;
public visitingShape(Shape shape) {
// Do logic related to the shape
}
public visitingCircle(Circle shape) {
// Do logic related to the circle
}
public visitingSquare(Square shape) {
// Do logic related to the square
}
}
I can propose an approach which is closer to pattern-matching. It doesn't solve the problem using inheritance, but it should give the same advantages as a visitor pattern without the heavyweight aspect of it.
Simply introduce a ShapeType enumeration, make each shape return its type and use a switch-case structure to implement your logic. Might be more readable.
It seems like you're in a pretty tough spot not owning the shape classes but I think you could add shape proxies. It adds an additional layer but provides the ability to extend the shapes as well as additional control over the interface if you'd need it.
Let's say, given a Shape as follows:
public class Shape {
public void doSomethingWithShape() {}
}
You provide a ShapeProxy like so (implementing the Shape interface and providing a proxy into it):
public class ShapeProxy extends Shape implements IShapeProxy {
// Optional
#Override
public void doSomethingWithShape() {
// Do something extra if needed.
}
// From IShapeProxy
#Override
public ExtendedShape getExtended() {
return new ExtendedShape(this);
}
}
Likewise, you would have proxies for each additional shape:
public class CircleProxy extends Circle implements IShapeProxy {
#Override
public ExtendedCircle getExtended() {
return new ExtendedCircle(this);
}
}
And, of course, you could use it like this:
public static void main(String[] args) {
List<IShapeProxy> shapes = new ArrayList<>();
shapes.add(new ShapeProxy());
shapes.add(new CircleProxy());
shapes.add(new SquareProxy());
List<ExtendedShape> extendedShapes = new ArrayList<>();
shapes.forEach(s -> extendedShapes.add(s.getExtended()));
}
I would prefer it this way but if you couldn't change the type of List then you could still shove them in as Shapes and cast to get the extended type. Still, it's a common cast that wouldn't require knowledge about the type of shape at hand.
If that seems like too much or if you'd like to separate the extending from the proxy, you can combine the proxy idea with Dici's suggestion and add a type like so (changes to the interface not shown):
public enum ShapeType {
SHAPE, CIRCLE, SQUARE
}
public class CircleProxy extends Circle implements IShapeProxy {
// From IShapeProxy
#Override
public ShapeType getType() {
return ShapeType.CIRCLE;
}
}
// And...
for (IShapeProxy proxy : shapes) {
switch (proxy.getType()) {
case SHAPE:
// Build the extended type.
break;
...
}
}
}
As you all know that the AbstractFactory helps creating object without knowledge of creation process. But the complexity of the pattern will increase by the time, when new factory is added or large modifications are made within the factory class. This will require a heavy change on abstract factory creator class.
I used to use AbstractFactory, but with my own modification & it's like: Replace abstract factory creator class with empty interface, which will be implemented by factory classes. Then cast returned object from FactoryCreator class to the real factory I want. This worked, but I wonder if this breaks the pattern or is it a bad practice on the pattern or does it have any drawback that would lead to the same complexity in the future development?
Below is a very simple implementation of the pattern that I took from the book & my modifications as well:
Shape factory:
public interface Shape {
void draw();
}
public class Circle implements Shape {
#Override
public void draw() {
// Draw circle
}
}
public class Rectangle implements Shape {
#Override
public void draw() {
// Draw rectangle
}
}
public class ShapeFactory implements IFactory {
public Shape getShape(String shape) {
if (shape.equalsIgnoreCase("CIRLE")) {
return new Circle();
} else if (shape.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
//public class ShapeFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Color factory:
public interface Color {
void fill();
}
public class Red implements Color {
#Override
public void fill() {
// Fill red
}
}
public class Green implements Color {
#Override
public void fill() {
// Fill green
}
}
public class ColorFactory implements IFactory {
public Color getColor(String color) {
if (color.equalsIgnoreCase("RED")) {
return new Red();
} else if (color.equalsIgnoreCase("GREEN")) {
return new Green();
}
}
}
//public class ColorFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Factory creator interface:
public interface IFactory { }
//public abstract class AbstractFactory {
// abstract Color getColor(String color);
// abstract Shape getShape(String shape) ;
//}
Factory creator:
public class FactoryCreator {
public static IFactory getFactory(String factoryName) {
if (factoryName.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
} else if (factoryName.equalsIgnoreCase("COLOR")) {
return new ColorFactory();
}
return null;
}
}
Usage:
public class demo {
ShapeFactory shapeFactory = (ShapeFactory)FactoryCreator.getFactory("SHAPE");
ColorFactory colorFactory = (ColorFactory)FactoryCreator.getFactory("COLOR");
shapeFactory.getShape("CIRCLE").draw();
shapeFactory.getShape("RECTANGLE").draw();
colorFactory.getColor("RED").fill();
colorFactory.getColor("GREEN").fill();
}
So the question in essence boils down to difference between abstract class and interface.
There are many sources on this discusion:
see here
What you need to understand about the patterns is that they are designed to be template for solution. It will happen rarely that you can copy paste pattern with zero modification and expect to fit your problem perfectly.
As for your question, can you implement AbstractFactory pattern with a FactoryCreator interface instead of abstract class ?
Surely you can, this is an implementation detail which does not break the intent of the pattern.
Abstract Factory offers the interface for creating a family of related objects, without explicitly specifying their classes.
Edit
You are looking at one specific implementation of this pattern in which author decided to implement the template with abstract class.
Design patterns are not a guarantee to to the right thing... you have to use your head first...
history showed that many people had a certain problem with [xxx] and a lot of people could solve the problem with Design-Pattern [yyy]. That's how desgin pattern evoveld and how they are defined.
You cannot say i'll implement this (or that) pattern and i'll have no problems anyway. you have to think, describe your problem and see if this pattern would help you to design your architecture.
Obviously: your programm implementation is so simple that abstractFactory is overhead, and you already solved that with using mere interfaces.
ok, let's speak the obvoius:
AbstractFactory is not the solution to your problem:
first: define your problem: i want to create parametrized objects in a simple way. a) parametrized with shape and color and b) simple way
possible solution: factory-methode (think: you have the interface Shape with two implementations and the interface Color with two implementations)
public ShapeFactory{
public static Shape create(String shape){
if ("CICRCLE".equals(shape)) //your code from above
}
}
and a Color factory
public ColorFactory{
public static Color createColor(String color){
if("GREEN".equals(color) ) // your code from above
}
}
using these design pattern you can solve your problem as defined above... (you can make one factory wich provides factory-methods for both interfaces, if you want to make it even shorter)
As per my understanding in the above problem, one wants to create a shape and then fill color in it. If thats the case one can make it bit better by adding Builder pattern on top of factory.
class ShapeBuider
{
private String color;
private String shape;
/**
* #param color the color to set
*/
public void setColor(String color) {
this.color = color;
}
/**
* #param shape the shape to set
*/
public void setShape(String shape) {
this.shape = shape;
}
public void build()
{
// create shape
// create color
// fill shape with color
}
public Object get()
{
// return the created object in build method here.
return null;
}
}
This builder approach will make sure that the right color is applied to right shape.
First I will just put my sample code.
public class Shape {
public String colour;
public Shape(String colour) {
this.colour = colour;
}
}
public class Car {
public String colour;
public Car (String colour) {
this.colour = colour;
}
}
public class Colour {
public static String getColour(Object item) {
return item.**colour**;
}
}
I've read other questions related to this, but I just can't seem to understand. I found their original code was just too complex for me to get around. So I tried to make as simple a code as possible. Anyway, I want getColour to accept both the Shape and Car object. If I use Object like I did in my example, the "colour" in bold is considered an error. The error I get is "colour cannot be resolved or is not a field". What's wrong?
Also, I've heard a lot of "static methods are bad" etc., is this a case of it being bad? Because I find if I don't make it static, then I need to duplicate getColour methods in both the Shape and Car classes. If I should avoid static methods, then please suggest another way to do this.
What you're looking for is the concept of interfaces:
public interface Colourable {
String getColour();
void setColour(String colour);
}
You should modify the Shape and Car classes:
public class Shape implements Colourable {
public Shape(String colour) {
this.colour = colour;
}
private String colour;
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
}
(note that I've made the colour field private; this is common practice and called encapsulation)
You can then define your static method as
public static String getColour(Colourable item) {
return item.getColour();
}
And static methods are definitely not bad, though in this case the method itself is a bit superfluous, because if you already have an Colourable, you know you can call .getColour() to get its color. A bit more useful would be the method
public static boolean isRed(Colourable item) {
return "red".equals(item.getColour());
}
You can "unify" Shape and Car. There are two general approaches:
Inheritance and
Interfaces
Let's look at both.
Inheritance: When a class Porsche inherits (or, in Java syntax, extends) a class Car, you establish an "is-a" relationship. In this case: Porsche is-a Car. Now, the magic comes to work, when you use object references. You can now write something like this:
Car c = new Porsche();
Since a Porsche has everything, a Car has (plus some things on top), you can see a Porsche as a Car (each Porsche is a Car, but not each Car is a Porsche). Reading my last sentence carefully, it is obvious, that the following does not work and, in fact, produces a compile error:
Porsche p = new Car();
What you can now do is write a method, that expects a Car and pass in a Porsche (since every Porsche is a Car).
Coming back to your example. To get this working, you could define a common parent class for Shape and Car, let's call it Colourable and give it a method public Colour getColour(). Then, you could simply change your getColour(Object item) method to getColour(Colourable c).
Remeber the thing I said about the "is-a" relation? Ask yourself: is each Shape a Colourable? Is each Car a Colourable? Why should Car and Shape both be in the same bucket (Colourable)? And what to do, if Car already has a parent class, e.g. Vehicle? This solution is sub-optimal.
Interfaces: This is, where interfaces come into play. Interfaces guarantee, that certain methods are present. Instead of defining a common parent class Colourable, you could simply write Colourable as an interface, containing the method public Colour getColour(). Now Shape and Car can implements this interface. This forces you to implement this method in both classes. The beauty: you can use interfaces just like classes. Meaning your implementation of getColour(Colourable c) does not need to change.
For more details, please read the provided tutorials on Inheritance and Interfaces.
Seems like your trying to use duck typing, which isn't how Java works.
The easiest thing to do, IMHO, would be to define an interface to handle the color. E.g.:
public interface Colourful {
public String getColour();
}
public class Shape implements Colorful {
private String colour;
public Shape(String colour) {
this.colour = colour;
}
#Override
public String getColour() {
return colour;
}
}
public class Car {
private String colour;
public Car (String colour) {
this.colour = colour;
}
#Override
public String getColour() {
return colour;
}
}
Alternatively, if you don't want to change Shape and Car, you could use reflection to extract the colour field, but this is usually considered a bad idea, and you'd probably be better off not using it:
public static String getColour(Object o) {
Field colourField;
try {
colourField = o.getClass().getField("colour");
} catch (NoSuchFieldException e) {
// No such field
return null;
}
Object colourValue;
try {
colourValue = colourField.get(o);
} catch (IllegalAccessException e) {
// The field isn't public
return null;
}
if (!(colourValue instanceof String)) {
// The field isn't a String
return null;
}
return (String) colourValue;
}
The reason an error is thrown is that Object doesn't have a colour field. I wouldn't recommend it, but if you want to move forward with this design, you could make a class called ShapeCarParent (used in this case because I see no clear relationship between the two) and have both the classes inherit from that, and then change getColour, like so:
public class ShapeCarParent{
public String colour;
}
public class Car extends ShapeCarParent
public class Shape extends ShapeCarParent
public class Colour {
public static String getColour(ShapeCarParent item) {
return item.colour;
}
}
This is still pretty poor style, so you can also use an interface which you then implement in each class.
public interface ColorProperties{
public String getColour();
}
public class Car implements ColorProperites{
public String getColour() {
return colour;
}
}
public class Shape implements ColorProperites{
public String getColour() {
return colour;
}
}
Hope this helps.
This question already has answers here:
What does it mean to program to an interface?
(17 answers)
Closed 9 years ago.
i have searched a lot but did not get exact answer for this Question hope i will get it from here.
what is exactly the use of referring object of a class to an interface instead of referring to the same class ??
void foo(list l){}
public static void main(String a[]){
List l = new ArrayList(); // why use this?
ArrayList a = new ArrayList(); //instead of this?
foo(l);
foo(a);
}
Maybe because an interface is something like a contract, which can be fullfilled by an implementation. You shouldn't depend on an implementation, because its about to change constantly, instead an interface/contract should not. Referring to an interface makes your implementation more robust.
Sometimes, the actual class of an instance does not matter, but only the interface it implements.
Also sometimes, it is impossible to know the actual class of an instance in compile time, but we only know the interface this class will implement.
For example, you have an interface called GeometricFigure
public static interface GeometricFigure {
public Double getGirth();
public String getName();
}
And you use this interface in a real class, for example, Canvas. Canvas has a list of GeometricFigures.
public class Canvas {
private List<GeometricFigure> figures;
public void printAllFigures() {
for (GeometricFigure figure : figures) {
System.out.println(figure.getName() + " " + figure.getGirth());
}
}
}
Now, your Canvas is independent of actual implementations of GeometricFigure. Canvas does not care how you is GeometricFigure is implemented, is it a square, circle or whatever. It only that this class can return a name and a girth so it can print them. So, the actual implementations can be Square, Circle, Triangle, etc. Only important thing is that these future classes implement the GemometricFigure interface.
For example:
public class Square implements GeometricFigure {
private String name;
private Double sideLength;
public Square(String name, Double sideLength) {
this.name = name;
this.sideLength = sideLength;
}
#Override
public Double getGirth() {
return 4 * sideLength;
}
#Override
public String getName() {
return name;
}
}