sorry for the long question and also my English.
I'm reading an article about DIP. I will summarize the code in here.
interface CoffeeMachine() {
void brewFilterCoffee();
}
interface EspressoMachine() {
void brewEspressoCoffee();
}
They create two different CoffeeMachine. BasicCoffeeMachine and PremiumCoffeeMachine. They both have the same feature is brewFilterCoffee(); so they put it on the CoffeeMachine interface
class BasicCoffeeMachine implements CoffeeMachine {
#Override
void brewFilterCoffee() {
System.out.println("brewing filter coffee...");
}
}
// this one can make Espresso
class PremiumCoffeeMachine implements CoffeeMachine, EspressoMachine {
#Override
void brewFilterCoffee() {
System.out.println("brewing filter coffee but in premium way...");
}
#Override
void brewEspressoCoffee() {
System.out.println("brewing espresso coffee...");
}
}
When they create CoffeeApp, it accepts CoffeeMachine interface in the constructor and uses it to prepareCoffee()
class CoffeeApp {
CoffeeMachine machine;
public CoffeeApp(CoffeeMachine machine) {
this.machine = machine;
}
public void prepareCoffee() {
machine.brewFilterCoffee();
}
}
In the Main class.
class Main {
public static void main(String[] args) {
PremiumCoffeeMachine premiumCoffeeMachine = new PremiumCoffeeMachine();
CoffeeApp app = new CoffeeApp(premiumCoffeeMachine);
app.brewFilterCoffee();
}
}
I left confused here because they didn't mention how they use brewEspressoCoffee() in CoffeeApp.
So I go ahead and modify CoffeeApp like this:
class CoffeeApp {
public void prepareFilterCoffee(CoffeeMachine machine) {
machine.brewFilterCoffee();
}
public void prepareEspressoCoffee(EspressoMachine machine) {
machine.brewEspressoCoffee();
}
}
In the Main class, if I want to brewEspressoCoffee(), I just create an instance that implements EspressoMachine
class Main {
public static void main(String[] args) {
PremiumCoffeeMachine premiumCoffeeMachine = new PremiumCoffeeMachine();
CoffeeApp app = new CoffeeApp();
app.brewEspressoCoffee(premiumCoffeeMachine);
}
}
Is this still the following DIP? And is there any better way to approach rather than this example? Any example would be appreciated.
Thank you!!
I think you've captured the essence of the DIP, which is that you can always insert an interface to invert the direction of a dependency.
Beyond just following the DIP, there is also the principle of Information Hiding to consider here. We often think of IH as applied to data, but it applies to dependencies as well.
In the original CoffeeApp, the client (customer) has no dependency on EspressoMachine and an indirect (transitive) dependency on CoffeeMachine. In the modified CoffeeApp, the client has direct dependencies on both Machine interfaces.
These dependencies are on abstractions, so the DIP is satisfied; but it begs the question, if CoffeeApp exposes its dependencies to its clients, then what is its purpose? Clients can invoke those dependencies directly. By passing on its dependencies, the CoffeeApp becomes useless.
Related
I am trying to figure out a way or a pattern to simplify my Service class and make it very adjustable. My aim would be for the method in Service class to be accessed for example with lambdas or Predicates.
class Client {
#RequestLine("something/a")
public A fetchA() {}
#RequestLine("something/b")
public B fetchB() {}
//... lots of similar methods
#RequestLine("something/z")
public Z fetchZ() {}
}
class Service {
Client client;
public void fixA(){
client.fetchA();
method();
}
public void fixB(){
client.fetchB();
method();
}
// ... lots of similar methods
public void fixZ(){
client.fetchZ();
method();
}
void method() {}
}
So my point how I could change it so it would use lambdas or something that would leave my Service class with one of the "fix" methods but it would know what I need to fetch from my Client.
If this question is bad and does not comply with rules here then please point me in the right direction as I am lost.
I guess what you want is
class Service {
private Client client;
public void fix(Consumer<Client> consumer){
consumer.accept(client);
method();
}
private void method() {}
}
that you can call using
service.fix(Client::fetchB);
One way would be to pass the call to your client as an argument to the method of your service. You'd need to use generics:
class Service {
Client client;
public <T> void fix(Function<Client, T> clientCall) {
T result = clientCall.apply(client);
// Do something with result
method();
}
}
You would need to call your service fix method as follows:
service.fix(Client::fetchA);
This question may be somewhat opinion based but let’s give it a try.
From my point of view the first design flaw you made is to put all the fetchXYZ methods into one client. You could create an interface Client that might look like this
interface Client<T> {
T fetch();
}
And create implementations of this interface like this:
public class ClientA implements Client<A> {
#RequestLine(”something/a“)
public A fetch() {
// do fetch stuff
}
}
You could store instances of the client implementations locally in a map or use a Factory pattern to create the right client depending on your input. And finally the fix method in your service might look like this:
public void fix(String clientType) {
// returns instance of ClientA for ’a‘ for example
final Client client = getClientForType(clientType);
client.fetch();
method();
}
There‘re probably plenty of ways to solve your requirements and this is just one of them.
I personally don’t like the idea of passing the client function as parameter to your method (although you asked for it) as in your current design Client has different responsibilities (fetches A, B and so on). Using lambdas actually enforces this flaw and furthermore hides what Client actually does.
Just my 2 cents.
Usually the point of Service is to be a facade over the Client. If that is the case with your example and you dont want to expose Clent class to the caller of Service you can go with single method and an enum like this:
public class Service {
Client client = new Client();
public enum FixType{
A(Client::fetchA),
B(Client::fetchB),
Z(Client::fetchZ);
private Consumer<Client> c = null;
private FixType(Consumer<Client> c) {
this.c = c;
}
private void fix(Client client) {
c.accept(client);
}
}
public void fix(FixType ft) {
ft.fix(client);
method();
}
void method() {}
}
And call fix by passing one of enums:
new Service().fix(Service.FixType.B);
Why not just
class Client {
public A fetch (String identifier) {
ArrayList<String> identifiers = ...;
// validate user-provided identifier here
if (___.equals(identifier)) {
// specific code for each identifier
} else if {
// ...etc.
}
}
}
class Service {
Client client;
public void fix (String identifier){
client.fetch(identifier);
method();
}
void method() {}
}
This may be a bit of a silly question, but I'm newish to Lamda Expressions and programming in General.
After experimenting around with Lambda Expression like so :
interface Starter {
public void start();
}
class Machine {
public void run( Starter s ) {
System.out.println("Running code....");
s.start();
}
}
public static void main(String[] args){
Machine mac1 = new Machine();
mac1.run(() -> System.out.println("Hello World"));
}
It made me wonder, if the Interface, and the class (Machine in this case) can be moved into seperate files for this to still work? I tried doing it how I think it would work, but that didn't work, is this possible? and if so how do you do it?
As long as the Machine class and Starter interface are visible to your main class, then this is perfectly possible.
My guess is that you moved the Starter interface to another package than the main class, and as you have not included the "public" modifier, it is no longer visible to the main class and will refuse to compile.
If I understood your problem correct, than just add a separate class (say App.class), that contains public static void main method:
public interface Starter {
public void start();
}
public class Machine {
public void run( Starter s ) {
System.out.println("Running code....");
s.start();
}
}
public class App {
public static void main(String[] args){
Machine mac1 = new Machine();
mac1.run(() -> System.out.println("Hello World"));
}
}
Context :
We are refectoring the code in order to move to micro services. We've
multiple products(A, B, C and some common code for A,B,C in monolithic
service). now we creating new sandbox for common code.
Problem :
User.java
Class User {
public **static** void init(){
List<Items> users=Items.getItemsList();
}
}
Items.java
Class Items {
public **static** Items getItemsList(){
//many static functions and dependancy
return items;
}
}
So here, both the functions are static and i want to move only User.java
to new sandbox not Items.java. how can i disintegrate this dependancy.
and i can not make User.init() non-static
Assuming sandbox means an independent project that produces a jar, then 'Items` must also exist in the sandbox, otherwise it won't compile.
But you could extract an interface from Items to something such as IItems (forgive the terrible name).
public interface IItems {
// methods...
}
which is included in the sandbox.
And create an interface for a factory such as:
public interface IItemsFactory {
List<IItem> create();
}
which is also included in the sandbox.
The ugly part is keeping User.init() as static. Using a hacky IoC pattern, set an implementation of an IItemsFactory into User. The factory will also have to be static. So User becomes something like:
public class User {
private static volatile IItemsFactory factory;
public static setFactory(IItemsFactory factory) {
User.factory = factory;
}
public static void init() {
List<IItems> users = factory.getItemsList();
}
}
The A, B, and C projects are responsible for providing an implementation of IItemFactory and setting it before calling User.init().
This is half baked and those static methods need to go away during the next refactoring iteration. Still use the IoC pattern, but inject the factory as part of the User constructor.
public class User {
private IItemsFactory factory;
public User(IItemsFactory factory) {
this.factory = factory;
}
public void init() {
List<IItems> users = factory.getItemsList();
}
}
In the following code (using Guice and Dependency Injection):
public class Main {
public static class Foo {
private FooInterface anInterface;
#Inject
Foo(FooInterface anInterface) {
this.anInterface = anInterface;
}
public void talk() {
anInterface.talk();
}
}
interface FooInterface {
void talk();
}
static class English implements FooInterface {
#Override
public void talk() {
System.out.println("Hello");
}
}
static class Spanish implements FooInterface {
#Override
public void talk() {
System.out.println("Hola");
}
}
public static class Module extends AbstractModule {
#Override
protected void configure() {
bind(FooInterface.class).to(English.class);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module());
Foo injectorInstanceFoo = injector.getInstance(Foo.class);
injectorInstanceFoo.talk();
Foo regularInstanceFoo = new Foo(new Spanish());
regularInstanceFoo.talk();
}
}
What is the advantage of using Guice(injectorInstanceFoo) to get instances of Foo over the "direct" way (regularInstanceFoo)?
Let's talk about what a program that uses your toy code might be like. Imagine that it is a console application, and the talk() method is needed when drawing the opening screen. In your settings, you control whether the English or the Spanish instance is bound (using a different module; don't use conditional logic INSIDE a module). The first advantage of using Dependency Injection is that your logic can easily control which language gets provided elsewhere in the code, so that callers don't all have to have logic to pick the implementation they want.
It also makes unit testing much easier - I'll go into a some more depth here to illustrate: You want to write some test code that tests the behavior of creating the message for your login screen. In this class LoginScreen, you #Inject a different FooInstance based on your regionalization settings:
public class LoginScreen {
private final String message;
#Inject
public LoginScreen(FooInstance foo) {
foo.talk();
// use other methods on foo that you didn't write
//
}
}
Now, you want to test the behavior of LoginScreen - not the behavior of FooInstance or its implementations. This syntax uses JUnit and Mockito (for conciseness), but it's fairly self explanatory:
public class LoginScreenTest() {
#Test
public void testMessage() {
FooInstance foo = mock(FooInstance.class);
LoginScreen screen = new LoginScreen(foo);
verify(foo).talk();
}
}
In this scenario, I don't care whether FooInstance is English or Spanish. I am trusting that those classes have been implemented correctly (and I would write a test for them in a different unit test). The contract of FooInstance is that talk() will write a greeting to the console - all I care about is that LoginScreen grabbed that greeting, but I don't care that FooInstance behaved correctly.
This isn't super meaningful in your example, because I could just call FooInstance foo = new English();. However, what if, instead of a System.out.println(), FooInstance had to load a database? Or what if it popped up a Swing dialog box? Or what if FooInstance had other dependencies? In all three of those cases it would be pretty painful to call new English() in your test.
Note: this is not the best way to do regionalization, but I'm just running with your example.
I couldn't think of a good way to name this. Basically I'm have a program where I want to have a default "pattern" almost I guess of how something should function. But I wanted to allow the use to create their own implementation (This is like an API) of the class and use that as a parameter instead, with the functionality inside. Is this the most efficient way to do it? If you don't understand that bad description here is an example.
public class SimpleStyle extends AbstractStyle {
public void personalizedImplementation() {
// manipulate the program this way
}
}
Then in the method
public static void do(Class<? extends AbstractSyle> style) {
// Use reflection in herre to get the implementation and do it
}
Is there a better and more efficient way to do something like this
You should not use reflection for this task if you can avoid it. It is less readable and more error-prone than well designed interfaces.
The basic solution (I’m not sure whether you already considered it) is to simply pass instances of AbstractStyle to your method:
public static void doSomething(AbstractStyle style) {
style.personalizedImplementation();
}
public static void main(String[] args) {
do(new SimpleStyle());
}
If you cannot use this approach – this depends on the specific use case – you could define an additional interface that handles the creation of the AbstractStyle instance:
public interface StyleFactory {
AbstractStyle createStyle();
}
public class SimpleStyleFactory implements StyleFactory {
#Override
public SimpleStyle createStyle() {
return new SimpleStyle(/* ... */);
}
}
public static void doSomething(StyleFactory styleFactory) {
AbstractStyle style = styleFactory.createStyle();
style.personalizedImplementation();
}
public static void main(String[] args) {
do(new SimpleStyleFactory());
}
Note: do is a Java keyword, so it can’t be used as an identifier. I used doSomething instead.