Which design pattern for merging 2 methods they differ in one place

Tags: , , ,



I wonder which design pattern should I use in my case: I have 2 endpoints that use 2 service methods, each very similar, they differ only in invoking some different methods from the same service:

My first service method (invoked by endpoint 1):

private Mono<Boolean> deleteAAA(
        List<SecuritySet> securitySets, boolean deleteRecoveryPoints) {
        return Flux.fromIterable(securitySets)
            .flatMap(
                protectionSet ->
                protectorRepository
                ...
                .flatMap(
                    protector ->
                    Mono.zip(
                        //some code)
                        .flatMap(
                            tuple ->
                            securityCommandService.sendUnprotectedAAA( // -> DIFFERENCE
                                tuple.getT1()))
                        .doOnNext(
                            securitySetId ->
                            subscriptionResourceService.cancelSubscriptionResources(
                                securitySet, protector))
                        .doOnNext(
                            //some code)
                            .map(
                                protectionSetId ->
                                createSecurityObject(securitySet, protector))
                            .doOnNext(schedulerService::deleteSecurity)))
                    .collectList()
                    .thenReturn(true);
                }

The second endpoint uses very similar method that differs in protectionCommandService.sendUnprotected (deleteBBB).

My secondservice method (invoked by endpoint 2):

private Mono<Boolean> deleteBBB(
        List<SecuritySet> securitySets, boolean deleteRecoveryPoints) {
        return Flux.fromIterable(securitySets)
            .flatMap(
                protectionSet ->
                protectorRepository
                ...
                .flatMap(
                    protector ->
                    Mono.zip(
                        //some code)
                        .flatMap(
                            tuple ->
                            securityCommandService.sendUnprotectedBBB( // -> DIFFERENCE
                                tuple.getT1()))
                        .doOnNext(
                            securitySetId ->
                            subscriptionResourceService.cancelSubscriptionResources(
                                securitySet, protector))
                        .doOnNext(
                            //some code)
                            .map(
                                protectionSetId ->
                                createSecurityObject(securitySet, protector))
                            .doOnNext(schedulerService::deleteSecurity)))
                    .collectList()
                    .thenReturn(true);
                }

I can pass to these methods deleteAAA and deleteBBB a parameter like Type type to somehow differentiate between the invoking of these methods. What would be the best way to merge these 2 methods into one method?

Answer

Abstract out what varies. You can pass functions as arguments with lambda expressions (or method references).

private Mono <Boolean> delete(List <SecuritySet> securitySets, Function<Tuple, List<Id>> unprotecedAAACall,
           boolean deleteRecoveryPoints) {
    return Flux.fromIterable(securitySets)
            .....//rest all same
            .flatMap(unprotecedAAACall)//function is passed in 
            ..... //rest all same       
}

In the above code, we pass a Function that maps a tuple to something. For demonstration, I have named that type as Id.

Call it as

private Mono <Boolean> deleteAAA(List <SecuritySet> securitySets, boolean deleteRecoveryPoints) {
    return delete(securitySets, tuple -> 
            securityCommandService.sendUnprotectedAAA(tuple.getT1()),
            deleteRecoveryPoints);
}

private Mono <Boolean> deleteBBB(List <SecuritySet> securitySets, boolean deleteRecoveryPoints) {
    return delete(securitySets, tuple -> 
            securityCommandService.sendUnprotectedBBB(tuple.getT1()),
            deleteRecoveryPoints);
}


Source: stackoverflow