10

In my project I need to create objects for each kind of Java Math Operator like "Add", "Substraction", "Multiplication", etc. And these operators should be singletons.

So here is what I am going to do. I define the Math Operator as an interface and I put those implementations inside it as I don't want to define singleton classes for each operator.

public interface MathOperator {


double operate(double a, double b);

MathOperator ADD = new MathOperator(){

    @Override
    public double operate(double a, double b) {
        return a + b;
    }

};

MathOperator SUBSTRACT = new MathOperator(){

    @Override
    public double operate(double a, double b) {
        return a - b;
    }

};  

}

I don't see much of such usage when I Google this. So I wonder if this is a good practice and if there are better and more graceful approaches?

0

6 Answers 6

5

I would do smt like

1) Define interface

interface MathOperator {
    double operate(double a, double b);
}

2) Than have some common implementation in enum (less code)

enum MathOperators implements MathOperator {
    ADD {
        @Override
        public double operate(double a, double b) {
            return a + b;
        }
    },

    SUBTRACT {
        @Override
        public double operate(double a, double b) {
            return a - b;
        }
    }
}

3) Or public static members (more clean solution).

class MathOperators {
    public static MathOperator ADD = new MathOperator() {
        @Override
        public double operate(double a, double b) {
            return a + b;
        }
    };
    public static MathOperator SUBTRACT = new MathOperator() {
        @Override
        public double operate(double a, double b) {
            return a - b;
        }
    };
}
  • can create new MathOperator without changing MathOperators
  • have nice API for common operations
  • shouldn't write singletons
  • have nice clean interface
Sign up to request clarification or add additional context in comments.

2 Comments

You need to make MathOperators implement MathOperator otherwise you are not @Override-ing anything.
Yep, this looks better I will take the 'enum implements interface' solution. Thanks.
5

One idiom that I've seen used in precisely these circumstances is the use of enum:

public enum MathOperator {

    ADD {
        @Override
        public double operate(double a, double b) {
            return a + b;
        }
    },

    SUBTRACT {
        @Override
        public double operate(double a, double b) {
            return a - b;
        }
    };

    public abstract double operate(double a, double b);

}

3 Comments

enums are OK when you have a finite number of possible impls, but when you just want some common ones handy, the interface constants rule. What you could do though is have enum MathOperatorImpl implements MathOperator! I like that even better!! :D
Thanks @Bohemian, I will take the 'enum implements interface' solution.
@Bohemian I remember such a recommendation in Effective Java, to use interfaces for emulating extensible enums. I think Jay is absoultely right to use this solution.
4

I use this pattern often, especially for specific implementations of generic interfaces. I find it works really well for me.

I like the way it puts the implementations where you can find them. I do it slightly differently - I make them static (it's a style thing, so the interface impls look more like class impls):

public interface MathOperator {

    double operate(double a, double b);

    public static MathOperator ADD = new MathOperator() {
        @Override
        public double operate(double a, double b) {
            return a + b;
        }
    };

    public static MathOperator SUBSTRACT = new MathOperator() {
        @Override
        public double operate(double a, double b) {
            return a - b;
        }
    };

}

1 Comment

yes, but for abstract classes I use static, so the code style stays consistent
2

I don't see any problem with it. Take java.lang.String.CASE_INSENSITIVE_ORDER for instance. It is almost the same, except that

  1. String is not an interface but a final class
  2. The Comparator is not declared using an anonymous class, but using a static inner class, which is essentially the same

Comments

1

Personally, I don't like putting implementations within interfaces. I would either:

  • make MathOperator an enum
  • keep the interface but have a factory or a static class (say MathOperators) with the implementations

Comments

0

Why don't you define each implementation in its own class/file? This would make it clearer and would leave the interface clean.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.