diff --git a/README.md b/README.md
index f47252648..8463ec21d 100644
--- a/README.md
+++ b/README.md
@@ -189,6 +189,15 @@
* a snapshot of an object's state must be saved so that it can be restored to that state later, and
* a direct interface to obtaining the state would expose implementation details and break the object's encapsulation
+##Model-View-Presenter
+**Intent:** Apply a "Separation of Concerns" principle in a way that allows developers to build and test user interfaces.
+
+
+
+**Applicability:** Use the Model-View-Presenter in any of the following situations
+* when you want to improve the "Separation of Concerns" principle in presentation logic
+* when a user interface development and testing is necessary.
+
##Observer
**Intent:** Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
diff --git a/model-view-presenter/etc/data/test.txt b/model-view-presenter/etc/data/test.txt
new file mode 100644
index 000000000..997ae361a
--- /dev/null
+++ b/model-view-presenter/etc/data/test.txt
@@ -0,0 +1,2 @@
+Test line 1
+Test line 2
\ No newline at end of file
diff --git a/model-view-presenter/etc/model-view-presenter.jpg b/model-view-presenter/etc/model-view-presenter.jpg
new file mode 100644
index 000000000..a51c914d0
Binary files /dev/null and b/model-view-presenter/etc/model-view-presenter.jpg differ
diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml
new file mode 100644
index 000000000..ef6a43260
--- /dev/null
+++ b/model-view-presenter/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ com.iluwatar
+ java-design-patterns
+ 1.0-SNAPSHOT
+
+ com.iluwatar
+ model-view-presenter
+ 1.0-SNAPSHOT
+ model-view-presenter
+ http://maven.apache.org
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+ net.java.dev.swing-layout
+ swing-layout
+ 1.0.2
+
+
+
diff --git a/model-view-presenter/src/main/java/com/iluwatar/FileLoader.java b/model-view-presenter/src/main/java/com/iluwatar/FileLoader.java
new file mode 100644
index 000000000..91c45ecca
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/FileLoader.java
@@ -0,0 +1,80 @@
+package com.iluwatar;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+/**
+ * Every instance of this class represents the Model component
+ * in the Model-View-Presenter architectural pattern.
+ *
+ * It is responsible for reading and loading the contents of a given file.
+ */
+public class FileLoader {
+
+ /**
+ * Indicates if the file is loaded or not.
+ */
+ private boolean loaded = false;
+
+ /**
+ * The name of the file that we want to load.
+ */
+ private String fileName;
+
+ /**
+ * Loads the data of the file specified.
+ */
+ public String loadData() {
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(new File(this.fileName)));
+ String text = "";
+ String line = "";
+
+ while( (line = br.readLine()) != null ) {
+ text += line + "\n";
+ }
+
+ this.loaded = true;
+ br.close();
+
+ return text;
+ }
+
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the path of the file to be loaded, to the given value.
+ *
+ * @param fileName The path of the file to be loaded.
+ */
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ /**
+ * @return fileName The path of the file to be loaded.
+ */
+ public String getFileName() {
+ return this.fileName;
+ }
+
+ /**
+ * @return True, if the file given exists, false otherwise.
+ */
+ public boolean fileExists() {
+ return new File(this.fileName).exists();
+ }
+
+ /**
+ * @return True, if the file is loaded, false otherwise.
+ */
+ public boolean isLoaded() {
+ return this.loaded;
+ }
+}
diff --git a/model-view-presenter/src/main/java/com/iluwatar/FileSelectorJFrame.java b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorJFrame.java
new file mode 100644
index 000000000..231128ca2
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorJFrame.java
@@ -0,0 +1,200 @@
+package com.iluwatar;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+
+/**
+ * This class is the GUI implementation of the View component
+ * In the Model-View-Presenter pattern.
+ */
+public class FileSelectorJFrame extends JFrame implements FileSelectorView, ActionListener {
+
+ /**
+ * Default serial version ID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The "OK" button for loading the file.
+ */
+ private JButton OK;
+
+ /**
+ * The cancel button.
+ */
+ private JButton cancel;
+
+ /**
+ * The information label.
+ */
+ private JLabel info;
+
+ /**
+ * The contents label.
+ */
+ private JLabel contents;
+
+ /**
+ * The text field for giving the name of the file
+ * that we want to open.
+ */
+ private JTextField input;
+
+ /**
+ * A text area that will keep the contents of the file opened.
+ */
+ private JTextArea area;
+
+ /**
+ * The panel that will hold our widgets.
+ */
+ private JPanel panel;
+
+ /**
+ * The Presenter component that the frame will interact with
+ */
+ private FileSelectorPresenter presenter;
+
+ /**
+ * The name of the file that we want to read it's contents.
+ */
+ private String fileName;
+
+ /**
+ * Constructor.
+ */
+ public FileSelectorJFrame() {
+ super("File Loader");
+ this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ this.setLayout(null);
+ this.setBounds(100, 100, 500, 200);
+
+ /*
+ * Add the panel.
+ */
+ this.panel = new JPanel();
+ panel.setLayout(null);
+ this.add(panel);
+ panel.setBounds(0, 0, 500, 200);
+ panel.setBackground(Color.LIGHT_GRAY);
+
+ /*
+ * Add the info label.
+ */
+ this.info = new JLabel("File Name :");
+ this.panel.add(info);
+ info.setBounds(30, 10, 100, 30);
+
+ /*
+ * Add the contents label.
+ */
+ this.contents = new JLabel("File contents :");
+ this.panel.add(contents);
+ this.contents.setBounds(30, 100, 120, 30);
+
+ /*
+ * Add the text field.
+ */
+ this.input = new JTextField(100);
+ this.panel.add(input);
+ this.input.setBounds(150, 15, 200, 20);
+
+ /*
+ * Add the text area.
+ */
+ this.area = new JTextArea(100, 100);
+ JScrollPane pane = new JScrollPane(area);
+ pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ this.panel.add(pane);
+ this.area.setEditable(false);
+ pane.setBounds(150, 100, 250, 80);
+
+ /*
+ * Add the OK button.
+ */
+ this.OK = new JButton("OK");
+ this.panel.add(OK);
+ this.OK.setBounds(250, 50, 100, 25);
+ this.OK.addActionListener(this);
+
+ /*
+ * Add the cancel button.
+ */
+ this.cancel = new JButton("Cancel");
+ this.panel.add(this.cancel);
+ this.cancel.setBounds(380, 50, 100, 25);
+ this.cancel.addActionListener(this);
+
+ this.presenter = null;
+ this.fileName = null;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if(e.getSource() == this.OK) {
+ this.fileName = this.input.getText();
+ presenter.fileNameChanged();
+ presenter.confirmed();
+ }
+
+ else if(e.getSource() == this.cancel) {
+ presenter.cancelled();
+ }
+ }
+
+ @Override
+ public void open() {
+ this.setVisible(true);
+ }
+
+ @Override
+ public void close() {
+ this.dispose();
+ }
+
+ @Override
+ public boolean isOpened() {
+ return this.isVisible();
+ }
+
+ @Override
+ public void setPresenter(FileSelectorPresenter presenter) {
+ this.presenter = presenter;
+ }
+
+ @Override
+ public FileSelectorPresenter getPresenter() {
+ return this.presenter;
+ }
+
+ @Override
+ public void setFileName(String name) {
+ this.fileName = name;
+ }
+
+ @Override
+ public String getFileName() {
+ return this.fileName;
+ }
+
+ @Override
+ public void showMessage(String message) {
+ JOptionPane.showMessageDialog(null, message);
+ }
+
+ @Override
+ public void displayData(String data) {
+ this.area.setText(data);
+ }
+}
diff --git a/model-view-presenter/src/main/java/com/iluwatar/FileSelectorPresenter.java b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorPresenter.java
new file mode 100644
index 000000000..3d1a22010
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorPresenter.java
@@ -0,0 +1,76 @@
+package com.iluwatar;
+
+/**
+ * Every instance of this class represents the Presenter component
+ * in the Model-View-Presenter architectural pattern.
+ *
+ * It is responsible for reacting to the user's actions and update the View component.
+ */
+public class FileSelectorPresenter {
+
+ /**
+ * The View component that the presenter interacts with.
+ */
+ private FileSelectorView view;
+
+ /**
+ * The Model component that the presenter interacts with.
+ */
+ private FileLoader loader;
+
+ /**
+ * Constructor
+ *
+ * @param view The view component that the presenter will interact with.
+ */
+ public FileSelectorPresenter(FileSelectorView view) {
+ this.view = view;
+ }
+
+ /**
+ * Sets the FileLoader object, to the value given as parameter.
+ *
+ * @param loader The new FileLoader object(the Model component).
+ */
+ public void setLoader(FileLoader loader) {
+ this.loader = loader;
+ }
+
+ /**
+ * Starts the presenter.
+ */
+ public void start() {
+ view.setPresenter(this);
+ view.open();
+ }
+
+ /**
+ * An "event" that fires when the name of the file to be loaded changes.
+ */
+ public void fileNameChanged() {
+ loader.setFileName(view.getFileName());
+ }
+
+ public void confirmed() {
+ if(loader.getFileName() == null || loader.getFileName().equals("")) {
+ view.showMessage("Please give the name of the file first!");
+ return;
+ }
+
+ if(loader.fileExists()) {
+ String data = loader.loadData();
+ view.displayData(data);
+ }
+
+ else {
+ view.showMessage("The file specified does not exist.");
+ }
+ }
+
+ /**
+ * Cancels the file loading process.
+ */
+ public void cancelled() {
+ view.close();
+ }
+}
diff --git a/model-view-presenter/src/main/java/com/iluwatar/FileSelectorStub.java b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorStub.java
new file mode 100644
index 000000000..a4b6cabf8
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorStub.java
@@ -0,0 +1,109 @@
+package com.iluwatar;
+
+/**
+ * Every instance of this class represents the Stub component in
+ * the Model-View-Presenter architectural pattern.
+ *
+ * The stub implements the View interface and it is useful when
+ * we want the test the reaction to user events, such as mouse clicks.
+ *
+ * Since we can not test the GUI directly, the MVP pattern provides
+ * this functionality through the View's dummy implementation, the Stub.
+ */
+public class FileSelectorStub implements FileSelectorView {
+
+ /**
+ * Indicates whether or not the view is opened.
+ */
+ private boolean opened;
+
+ /**
+ * The presenter Component.
+ */
+ private FileSelectorPresenter presenter;
+
+ /**
+ * The current name of the file.
+ */
+ private String name;
+
+ /**
+ * Indicates the number of messages that were "displayed" to the user.
+ */
+ private int numOfMessageSent;
+
+ /**
+ * Indicates if the data of the file where displayed or not.
+ */
+ private boolean dataDisplayed;
+
+ /**
+ * Constructor
+ */
+ public FileSelectorStub() {
+ this.opened = false;
+ this.presenter = null;
+ this.name = "";
+ this.numOfMessageSent = 0;
+ this.dataDisplayed = false;
+ }
+
+ @Override
+ public void open() {
+ this.opened = true;
+ }
+
+ @Override
+ public void setPresenter(FileSelectorPresenter presenter) {
+ this.presenter = presenter;
+ }
+
+ @Override
+ public boolean isOpened() {
+ return this.opened;
+ }
+
+ @Override
+ public FileSelectorPresenter getPresenter() {
+ return this.presenter;
+ }
+
+ @Override
+ public String getFileName() {
+ return this.name;
+ }
+
+ @Override
+ public void setFileName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void showMessage(String message) {
+ this.numOfMessageSent++;
+ }
+
+ @Override
+ public void close() {
+ this.opened = false;
+ }
+
+ @Override
+ public void displayData(String data) {
+ this.dataDisplayed = true;
+ }
+
+ /**
+ * Returns the number of messages that were displayed to the user.
+ */
+ public int getMessagesSent() {
+ return this.numOfMessageSent;
+ }
+
+ /**
+ * @return True if the data where displayed, false otherwise.
+ */
+ public boolean dataDisplayed() {
+ return this.dataDisplayed;
+ }
+}
diff --git a/model-view-presenter/src/main/java/com/iluwatar/FileSelectorView.java b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorView.java
new file mode 100644
index 000000000..deb1bd841
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/FileSelectorView.java
@@ -0,0 +1,62 @@
+package com.iluwatar;
+
+/**
+ * This interface represents the View component in the
+ * Model-View-Presenter pattern. It can be implemented
+ * by either the GUI components, or by the Stub.
+ */
+public interface FileSelectorView {
+
+ /**
+ * Opens the view.
+ */
+ public void open();
+
+ /**
+ * Closes the view.
+ */
+ public void close();
+
+ /**
+ * @return True, if the view is opened, false otherwise.
+ */
+ public boolean isOpened();
+
+ /**
+ * Sets the presenter component, to the one given as parameter.
+ *
+ * @param presenter The new presenter component.
+ */
+ public void setPresenter(FileSelectorPresenter presenter);
+
+ /**
+ * @return The presenter Component.
+ */
+ public FileSelectorPresenter getPresenter();
+
+ /**
+ * Sets the file's name, to the value given as parameter.
+ *
+ * @param name The new name of the file.
+ */
+ public void setFileName(String name);
+
+ /**
+ * @return The name of the file.
+ */
+ public String getFileName();
+
+ /**
+ * Displays a message to the users.
+ *
+ * @param message The message to be displayed.
+ */
+ public void showMessage(String message);
+
+ /**
+ * Displays the data to the view.
+ *
+ * @param data The data to be written.
+ */
+ public void displayData(String data);
+}
diff --git a/model-view-presenter/src/main/java/com/iluwatar/MainApp.java b/model-view-presenter/src/main/java/com/iluwatar/MainApp.java
new file mode 100644
index 000000000..cd342d539
--- /dev/null
+++ b/model-view-presenter/src/main/java/com/iluwatar/MainApp.java
@@ -0,0 +1,12 @@
+package com.iluwatar;
+
+public class MainApp {
+
+ public static void main(String[] args) {
+ FileLoader loader = new FileLoader();
+ FileSelectorJFrame jFrame = new FileSelectorJFrame();
+ FileSelectorPresenter presenter = new FileSelectorPresenter(jFrame);
+ presenter.setLoader(loader);
+ presenter.start();
+ }
+}
diff --git a/model-view-presenter/src/test/java/com/iluwatar/FileSelectorPresenterTest.java b/model-view-presenter/src/test/java/com/iluwatar/FileSelectorPresenterTest.java
new file mode 100644
index 000000000..507cad251
--- /dev/null
+++ b/model-view-presenter/src/test/java/com/iluwatar/FileSelectorPresenterTest.java
@@ -0,0 +1,122 @@
+package com.iluwatar;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This test case is responsible for testing our application
+ * by taking advantage of the Model-View-Controller architectural pattern.
+ */
+public class FileSelectorPresenterTest {
+
+ /**
+ * The Presenter component.
+ */
+ private FileSelectorPresenter presenter;
+
+ /**
+ * The View component, implemented this time as a Stub!!!
+ */
+ private FileSelectorStub stub;
+
+ /**
+ * The Model component.
+ */
+ private FileLoader loader;
+
+
+ /**
+ * Initializes the components of the test case.
+ */
+ @Before
+ public void setUp() {
+ this.stub = new FileSelectorStub();
+ this.loader = new FileLoader();
+ presenter = new FileSelectorPresenter(this.stub);
+ presenter.setLoader(loader);
+ }
+
+ /**
+ * Tests if the Presenter was successfully connected with the View.
+ */
+ @Test
+ public void wiring() {
+ presenter.start();
+
+ assertNotNull(stub.getPresenter());
+ assertTrue(stub.isOpened());
+ }
+
+ /**
+ * Tests if the name of the file changes.
+ */
+ @Test
+ public void updateFileNameToLoader() {
+ String EXPECTED_FILE = "Stamatis";
+ stub.setFileName(EXPECTED_FILE);
+
+ presenter.start();
+ presenter.fileNameChanged();
+
+ assertEquals(EXPECTED_FILE, loader.getFileName());
+ }
+
+ /**
+ * Tests if we receive a confirmation when we attempt to open a file
+ * that it's name is null or an empty string.
+ */
+ @Test
+ public void fileConfirmationWhenNameIsNull() {
+ stub.setFileName(null);
+
+ presenter.start();
+ presenter.fileNameChanged();
+ presenter.confirmed();
+
+ assertFalse(loader.isLoaded());
+ assertEquals(1, stub.getMessagesSent());
+ }
+
+ /**
+ * Tests if we receive a confirmation when we attempt to open a file
+ * that it doesn't exist.
+ */
+ @Test
+ public void fileConfirmationWhenFileDoesNotExist() {
+ stub.setFileName("RandomName.txt");
+
+ presenter.start();
+ presenter.fileNameChanged();
+ presenter.confirmed();
+
+ assertFalse(loader.isLoaded());
+ assertEquals(1, stub.getMessagesSent());
+ }
+
+ /**
+ * Tests if we can open the file, when it exists.
+ */
+ @Test
+ public void fileConfirmationWhenFileExists() {
+ stub.setFileName("etc/data/test.txt");
+ presenter.start();
+ presenter.fileNameChanged();
+ presenter.confirmed();
+
+ assertTrue(loader.isLoaded());
+ assertTrue(stub.dataDisplayed());
+ }
+
+ /**
+ * Tests if the view closes after cancellation.
+ */
+ @Test
+ public void cancellation() {
+ presenter.start();
+ presenter.cancelled();
+
+ assertFalse(stub.isOpened());
+ }
+}
diff --git a/pom.xml b/pom.xml
index 4da45cbe6..6f43e6cc7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
iterator
mediator
memento
+ model-view-presenter
observer
state
strategy
@@ -59,4 +60,4 @@
-
\ No newline at end of file
+