javaswingchain-of-responsibility

How to implement chain of responsibility with Java Swing


I have the task of creating a simple drawing app, where one can draw basic shapes (ovals,lines,rectangles) with border and fill colors of choice, using Java Swing and MVC.

The shapes part of the model is implemented using the composite pattern. The functionality to be implementing is drawing (this is already handled by the shapes classes themselves), resizing, moving and deleting shapes and I am supposed to use chain of responsibility (CoR) pattern to accomplish this.

CoR makes sense to me in theory, but I have difficulty grasping how I can apply it for implementing the functionality in practice. I understand that when I click on the drawing panel the program should recognize which shape is selected and then I can implement the methods for resizing,moving,deleting.

So what I need advice on is:

1) how to practically implement CoR pattern here?

2) what is a good way to implement the functionality for resizing, moving, deleting? In own concrete handler classes, as methods in the shapes classes, other?

Many thanks for help.


Solution

  • Here is a proposed basic implementation of CoR.
    For ease of use the following code is a one-file mre : the entire code can be copy-pasted into ShapeManipulator.java and run:

    public class ShapeManipulator {
    
        public static void main(String[] args) {
            Shape s1 = new Shape();
            Shape s2 = new Shape();
            Shape s3 = new Shape();
    
            ShapeManipulationBase move = new MoveHandler();
            ShapeManipulationBase resize = new ResizeHandler();
            ShapeManipulationBase delete = new DeleteHandler();
    
            move.setXparam(50).setYparam(25).handle(s1);
            resize.setXparam(100).setYparam(250).handle(s1);
            resize.setXparam(200).setYparam(20).handle(s2);
            delete.handle(s3);
        }
    }
    
    //CoR basic interface 
    interface ShapeManipulationHandler {
         void handle(Shape shape);
    }
    
    //base class allows swtting of optional x, y parameters 
    abstract class ShapeManipulationBase implements ShapeManipulationHandler {
    
        protected int Xparam, Yparam; 
    
        //setters return this to allow chaining of setters 
        ShapeManipulationBase setXparam(int xparam) {
            Xparam = xparam;
            return this;
        }
    
        ShapeManipulationBase setYparam(int yparam) {
            Yparam = yparam;
            return this;
        }
    
        @Override
        public abstract void handle(Shape shape) ;
    }
    
    class MoveHandler extends ShapeManipulationBase {
    
        @Override
        public void handle(Shape shape) {
            System.out.println("Moving "+ shape + " by X="+ Xparam + " and Y="+ Yparam);
        }
    }
    
    class ResizeHandler extends ShapeManipulationBase {
    
        @Override
        public void handle(Shape shape) {
            System.out.println("Resizing "+ shape + " by X="+ Xparam + " and Y="+ Yparam);
        }
    }
    
    class DeleteHandler extends ShapeManipulationBase {
    
        @Override
        public void handle(Shape shape) {
            System.out.println("Deleting "+ shape);
        }
    }
    
    class Shape{
        private static int shapeCouner = 0;
        private final int shapeNumber;
    
        Shape() {
            shapeNumber = ++shapeCouner;
        }
    
        @Override
        public String toString() {
            return "Shape # "+shapeNumber;
        }
    }