[![enter image description here][1]][1]

You can call it ports and adapters or hexagonal architecture. Regardles what's facinated me about this picture isn't the layers. It's the UML diagram in the corner that looks like a folded over version of the Dependency Inversion Principle:

[![enter image description here][2]][2]

Some like to think of an interface like it's owned by the class that implements it.

Some like to think of an interface like it's owned by the client that uses it.

For the first time I'm starting to think either can be true. Both interfaces are really owned by the inner layer.

I've written some example code that is just suposed to show how these layer plugins might look. Please check it for clarity.

Ordered to follow the flow of control:

 package candiedOrange.plugin.adapters;
 
 import candiedOrange.plugin.usecases.ButtonUseCaseInputPort;
 
 public class ButtonControler {
 ButtonUseCaseInputPort button;

 public ButtonControler(ButtonUseCaseInputPort button) {
 this.button = button;
 }
 
 public void push() {
 button.push();
 }
 }

 

 package candiedOrange.plugin.usecases;
 
 public interface ButtonUseCaseInputPort {
 void push();
 }
 
 

 package candiedOrange.plugin.usecases;

 public class ButtonPushUseCaseInteractor implements ButtonUseCaseInputPort {
 ButtonUseCaseOutputPort outputPort;

 public ButtonPushUseCaseInteractor(ButtonUseCaseOutputPort outputPort){
 this.outputPort = outputPort;
 }

 @Override
 public void push() {
 outputPort.push();
 }
 }

 

 package candiedOrange.plugin.usecases;
 
 public interface ButtonUseCaseOutputPort {
 void push();
 }

 

 package candiedOrange.plugin.adapters;
 
 import candiedOrange.plugin.usecases.ButtonUseCaseOutputPort;
 
 public class ButtonPresenter implements ButtonUseCaseOutputPort{
 
 @Override
 public void push() {
 System.out.print("push");
 }
 }

And some tests:

 package candiedOrange.plugin;
 
 import candiedOrange.plugin.adapters.ButtonControler;
 import candiedOrange.plugin.adapters.ButtonPresenter;
 import candiedOrange.plugin.usecases.ButtonPushUseCaseInteractor;
 import candiedOrange.plugin.usecases.ButtonUseCaseInputPort;
 import candiedOrange.plugin.usecases.ButtonUseCaseOutputPort;

 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 

 public class TestCleanArchitecture {
 
 private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
 
 private PrintStream oldStdOut;
 
 @Before
 public void setUpStreams() {
 oldStdOut = System.out;
 System.setOut(new PrintStream(outContent));
 }
 
 @After
 public void cleanUpStreams() {
 System.setOut(oldStdOut);
 }

 
 
 @Test
 public void testOut() {
 System.out.print("hello");
 assertEquals("hello", outContent.toString());
 }
 
 @Test
 public void testPresenter() {
 outContent.reset();
 new ButtonPresenter().push();
 assertEquals("push", outContent.toString());
 }
 
 static class PushMock implements ButtonUseCaseInputPort, ButtonUseCaseOutputPort{
 boolean pushed;
 public boolean isPushed() { return pushed; }
 public void push() { this.pushed = true; }
 }
 
 

 @Test
 public void testInteractor() {
 PushMock presentorMock = new PushMock();
 assertFalse(presentorMock.isPushed());
 new ButtonPushUseCaseInteractor(presentorMock).push();
 assertTrue(presentorMock.isPushed());
 }

 @Test
 public void testControler() {
 PushMock interactorMock = new PushMock();
 assertFalse(interactorMock.isPushed());
 new ButtonControler(interactorMock).push();
 assertTrue(interactorMock.isPushed());
 }
 
 @Test
 public void testEndToEnd() {
 outContent.reset();
 new ButtonControler(new ButtonPushUseCaseInteractor(new ButtonPresenter())).push();
 assertEquals("push", outContent.toString());
 }
 }

Package structure: 
[![enter image description here][3]][3]

Looking to make the above into a readable example. Critical input welcome.


 [1]: https://i.sstatic.net/uhHZ5.jpg
 [2]: https://i.sstatic.net/VrV8b.png
 [3]: https://i.sstatic.net/EvyGU.png