8

I have Java enum:

public enum ConflictResolutionStrategy {
    softResolve,
    hardResolve,
}

I want to call it like ConflictResolutionStrategy.hardResolve.apply(case1, case2).

Both case1 and case2 objects of the same type. apply in my case should return nothing.

The basic idea behind this design. Create Strategy design pattern and resolve conflicts based on the set enum value.

I cannot find any similar questions on StackOveflow even simple search gives me tons of similar cases which don't resolve my case directly.

I tried The following:

public enum ConflictResolutionStrategy {
    softResolve ((CaseType case1, CaseType case2) -> case1.update(case2)),
    hardResolve,
}

This version above doesn't compile.

I tried another solution:

public enum ConflictResolutionStrategy {
    softResolve,
    hardResolve {
        public void apply(CaseType case1, CaseType case2) {
            case1.update(case2);
        }
    },
}

The second solution, works okay but requires too much code.

Naman
  • 27,789
  • 26
  • 218
  • 353
Dmytro Chasovskyi
  • 3,209
  • 4
  • 40
  • 82
  • 3
    well obviously `softResolve` and `hardResolve` are actually solved in different ways, so you have to override `apply` for them to handle that in different ways... so "too much code" will be required, yes – Eugene Feb 05 '19 at 14:14
  • @Eugene Since `softResolve` and `hardResolve` are different values and should be treated differently. I do understand that different code should be in both cases. The main point of my question if I can write in `lambda`-like style way the same what works in the last my code sample? I want to reduce noise of the code buy using modern `Java` features. – Dmytro Chasovskyi Feb 05 '19 at 14:27

2 Answers2

7

A function accepting two parameters and returning nothing is a BiConsumer.

Your enum may implement BiConsumer:

public enum ConflictResolutionStrategy implements BiConsumer<CaseType, CaseType> {
    softResolve ((case1, case2) -> case1.update(case2)),
    hardResolve((case1, case2) -> {/* do something else */});

    private final BiConsumer<CaseType, CaseType> consumer;

    ConflictResolutionStrategy(BiConsumer<CaseType, CaseType> consumer){
        this.consumer = consumer;
    }

    @Override
    public void accept(CaseType case1, CaseType case2) {
        consumer.accept(case1, case2);
    }

}

Suppose you have a method for processing your cases:

public void processCases(Collection<CaseType> cases, BiConsumer<CaseType, CaseType> conflictResolutionStrategy){
    // ...
}

Now you can pass in either one of your existing strategies:

processCases(cases, ConflictResolutionStrategy.softResolve);

or an inline strategy:

processCases(cases, (c1, c2) -> { /* do smth here */ }); 
ETO
  • 6,970
  • 1
  • 20
  • 37
1

Maybe you're looking for something like a BiConsumer within the enum as :

public enum ConflictResolutionStrategy {
    softResolve(CaseType::update), // just for example
    hardResolve((caseType, caseType2) -> {
        caseType.update(caseType2);
    }); // lambda representation

    BiConsumer<CaseType, CaseType> caseTypeBiConsumer;

    ConflictResolutionStrategy(BiConsumer<CaseType, CaseType> caseTypeBiConsumer) {
        this.caseTypeBiConsumer = caseTypeBiConsumer;
    }
}


class CaseType {
    void update(CaseType caseType){}
}
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 2
    how would you use that btw? provide that example in the question also - and you will see that you are just deferring the same "too much code" to a different place. – Eugene Feb 05 '19 at 14:48
  • @Eugene agreed that code would have to be written somewhere for sure, in this case, `update` or other such implementation would be the block. Just brought this up to better bind type and relate to the version that OP tried and didn't compile for them. – Naman Feb 05 '19 at 14:50
  • @nullpointer This compiles for me but how can I call `BiConsumer` from my `enum`? I try something like `ConflictResolutionStrategy conflictStrategy = ConflictResolutionStrategy.softResolve; conflictStrategy.accept(case1, case2)` but `accept` method not visible. Am I doing something wrong? – Dmytro Chasovskyi Feb 05 '19 at 15:13
  • 1
    @DmytroChasovskyi It would have to be `conflictStrategy.caseTypeBiConsumer.accept` – Naman Feb 05 '19 at 15:15