Skip to content

Instantly share code, notes, and snippets.

@le-doude
Last active November 7, 2019 03:04
Show Gist options
  • Save le-doude/6bbd8b3db9029af117a24a01d54e273c to your computer and use it in GitHub Desktop.
Save le-doude/6bbd8b3db9029af117a24a01d54e273c to your computer and use it in GitHub Desktop.
// here is an example of bad implementation that breaks encapsulation AND is hard to extend
class MyService {
void doSomethingWith(MyInterface instance) {
if(instance instanceof FirstImpl) {
doSomething((FirstImpl) instance);
} else if (instance instanceof SecondImpl) {
doSomethingElse((SecondImpl) instance);
} else {
defaultBehaviour(instance);
}
}
}
// here is the same code but the decision
interface MyInterface {
// here we use a consumer interface but we can directly return values or do computations or return values directly.
Consumer<MyInterface> somethingThatDoesSomething();
}
class FirstImpl implements MyInterface {
Consumer<MyInterface> somethingThatDoesSomething() {
return // ...
}
}
class SecondImpl implements MyInterface {
Consumer<MyInterface> somethingThatDoesSomething() {
return // ...
}
}
class DefaultImpl implements MyInterface {
Consumer<MyInterface> c() {
return // ...
}
}
class MyService {
void doSomethingWith(MyInterface instance) {
instance.somethingThatDoesSomething().accept(instance);
}
}
@le-doude
Copy link
Author

le-doude commented Nov 7, 2019

The second approach allows us to create new implementations of MyInterface without ever having to modify MyService.
So the point is to have a common interface that is used by all services AND WITHOUT exception have the parameter provide the "customized" implementation of its own type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment