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.
Related
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;
...
}
}
}
I'm learning Desgin patterns and come across very weird example in HERE. If we got a class:
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
which as we can see, has 2 types of methods which creates Objects: colors and shapes. This class is abstract so we have to create concrete implementation of this, so lets assume that we have:
public class ShapeFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
// I skip implementation to keep post brief
}
#Override
Color getColor(String color) {
return null; // It's useless method in this class!
}
}
and second implementation:
public class ColorFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
return null; // It's useless method in this class!
}
#Override
Color getColor(String color) {
// I skip implementation to keep post brief
}
}
And here comes my question, in both cases (concrete factories) there is an method that is completly useless and shoudn't be there, but as we created AbstractFactory class we have to implement both methods. Isn't it bad practice in programming to create useless methods in classes that don't need it? Should it be done in other way not as website suggest?
#Michael213 - Your concrete implementations are not correct. For sure they do not follow Abstract Factory pattern. Abstract factory talks about families of product. abstract factory sample (with my assumptions) will look like following code. your example using only one method will be misuse of pattern and will break soon.
I have already answer similar question please have a look to that also What are the real benefits of using the Abstract Factory in the following example, instead of the factory method?
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
/**
* CONCRETE FACTORY1
*/
class HighResolutionFactory extends AbstractFactory{
Color getColor(String color){
return new HighResolutionColor();
}
Shape getShape(String shape){
return new HighResolutionShape();
}
}
/**
* CONCRETE FACTORY2
*/
class LowResolutionFactory extends AbstractFactory{
Color getColor(String color){
return new LowResolutionColor();
}
Shape getShape(String shape){
return new LowResolutionShape();
}
}
class Color{} // ABSTRACT PRODUCT 1
class Shape{} // ABSTRACT PRODUCT 2
class HighResolutionColor extends Color{}// CONCRETE PRODUCT1 FACT 1
class HighResolutionShape extends Shape{}// CONCRETE PRODUCT2 FACT 1
class LowResolutionColor extends Color{}//...
class LowResolutionShape extends Shape{}
Yes, that tutorial doesn't seem the best in that regards.
It is not ideal although it still counts as a factory design pattern.
AbstractFactory is wrong. You do not have to think of a factory that makes different objects. It is right to make separate factories for each different type.
public interface AbstractColorFactory {
public Color getColor(String color);
}
public interface AbstractShapeFactory {
public Shape getShape(String shape);
}
public class ColorFactory implements AbstractColorFactory {
public Color getColor(String color) {
return ....
}
}
public class ShapeFactory implements AbstractShapeFactory {
public Shape getShape(String shape) {
return ....
}
}
I am creating a editor for different Shape Objects. I stumbled upon the visitor pattern which actually fits my needs I think.
I have a Element class which holds a field named attrs
public class Element {
...
private Shape attrs;
...
}
My Shape class looks like this with the visitor design pattern.
public abstract class Shape {
public abstract void accept(ShapeVisitor v);
public interface ShapeVisitor{
public void visit(CircleObject circle);
public void visit(RectangleObject rectangle);
}
}
And the actual instance of a Shape is defined in a RectangleObject class which extends Shape and holds the Rectangle field. The reasoning for this structure is that I am serializing and deserializing with Jackson for a specifig JSON layout.
public class RectangleObject extends Shape {
private Rectangle rect;
public class Rectangle {
private String fill;
public String getFill() {
return fill;
}
public void setFill(String fill) {
this.fill = fill;
}
#Override
public void accept(JointShapeVisitor v) {
v.visit(this);
}
}
And finally my Editor implements the vistor methods.
public class Editor implements ShapeVisitor{
#Override
public void visit(CircleObject circle) {
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
visit(element.getAttrs()); // *** this does obv. not work ***
}
}
The element.getAttrs() returns JointShape, but I need here a CircleObject or a RectangleObject.
How can I pass the correct instance of the ShapeObject to the visit method? Am I doing something completely wrong?
Best regards.
Well ... one little mistake. Because you correctly declared an accept method in your Shape class, you simply must call it:
element.getAttrs().accept(this);
So simply call the accepting method of a shape by providing the editor itself as a visitor. The callback in the shape implementation will call the correct visitor mehod.
What you would do is
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
element.getAttrs().accept(this);
}
And you'll get a callback into one of the visit methods. What you don't get is a return value.
This can be a bit tricky to handle because the callback code is suddenly in no relation to the method that called the accept method. But you often want to pass arguments back and forth between the visiting method and the method that that called accept. To do that, you can add a little to the pattern:
#Override
public Object accept(JointShapeVisitor v, Object context) {
return v.visit(this, context);
}
}
public interface ShapeVisitor{
public Object visit(CircleObject circle, Object context);
..
}
Maybe with a bit of generics to make it typesafe. But even without you can suddenly do
public class Editor implements ShapeVisitor{
#Override
public Foo visit(CircleObject circle, Object context) {
return new Foo(circle, (String) context));
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
Foo foo = (Foo)element.getAttrs().visit(this, "Hello");
}
}
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.
I have a superclass Shape, and classes Triangle, Square, etc. extend Shape. I have two current issues:
My method Triangle extends Shape does not compile. It has to return a Shape, not a Triangle.
I want to hide this method. It should only be callable from the Shape superclass.
public class Shape {
public static Shape createShapeFromXML(String xml) {
String type = parse(xml);
if (type.equals("Triangle") {
Triangle.createShapeFromXML(xml);
} else if (...) {
// ...
}
}
}
public class Triangle extends Shape {
public static Triangle createShapeFromXML(String xml) {
....
}
}
public static void main(String[] args) {
String xml = ...
Shape s = Shape.createShapeFromXML(xml);
}
How can I resolve these issues?
why don't you keep the one static method in the superclass, and have it return the appropriate Shape subclass? The signature would stay the same because Triangles have an is-a relationship to Shape.
You could make the method on the superclass private to get the access restriction you want...
Another approach would be to use the Factory pattern. You could have a ShapeFactory...
This is a good idea because creating the xml parsing is not a concern of the Shape classes. Separate your concerns. The wikipedia link is good at describing the pattern, but you might want a simpler example. See this.
// 2. I want to hide this method. It should only be callable from superclass Shape
You can make the Shape method final in order to lock down the implementation. Even your overloaded method that returns a subclass type (Triangle in your example) would be flagged by the compiler.
public static final Shape createShapeFromXML(String xml) { ... }
EDIT:
in response to the conversation in the comments, for evidence I provide the following:
public class Shape {
public static final Shape createShapeFromXML(String xml) {
if (xml.equals("Triangle")) {//removed parse for demo compliation
return Triangle.createShapeFromXML(xml);
} else {
return new Shape();
}
}
}
public class Triangle extends Shape{
public static Triangle createShapeFromXML(String xml) {
return new Triangle();
}
}
trying to compile the above will result in a compiler error:
mybox:src akf$ javac Triangle.java
Triangle.java:3: createShapeFromXML(java.lang.String) in Triangle cannot override createShapeFromXML(java.lang.String) in Shape; overridden method is static final
public static Triangle createShapeFromXML(String xml) {
^
1 error
This can be explained using the JLS by referencing two sections:
from 8.4.6.2 Hiding (by Class Methods):
If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class.
and then from 8.4.3.3 final Methods:
A method can be declared final to prevent subclasses from overriding or hiding it. It is a compile-time error to attempt to override or hide a final method.
Putting the two together, adding final to the signature of a static method will protect that method from being hidden by subclasses. It will enforce compile-time checking.
To make your code compile you need to declare public static Shape createShapeFromXML(String xml) in the Triangle class.
public class Shape {
public static void main(String[] args) {
String xml = "Triangle";
Shape s = Shape.createShapeFromXML(xml);
System.out.println(s.toString());
}
public static Shape createShapeFromXML(String xml) {
Shape aShape = null;
if (xml.equals("Triangle")) {
aShape = Triangle.createShapeFromXML(xml);
}
return aShape;
}
}
class Triangle extends Shape {
public static Shape createShapeFromXML(String xml) {
return new Triangle();
}
#Override
public String toString() {
return "Triangle";
}
}
The System.out.println(s.toString()); in the main method outputs "Triangle", this proves that a Triangle shape is being created.