© Vaskaran Sarcar 2019
Vaskaran SarcarJava Design Patternshttps://doi.org/10.1007/978-1-4842-4078-6_26

26. MVC Pattern

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

Model-View-Controller (MVC) is an architectural pattern.

The use of this pattern is commonly seen in web applications or when we develop powerful user interfaces. But it is important to note that Trygve Reenskaug first described MVC in 1979 in a paper titled, “Applications Programming in Smalltalk-80TM: How to Use Model-View-Controller,” which was before the World Wide Web era. At that time, there was no concept of web applications. But modern-day applications can be seen as an adaptation of that original concept. It is important to note that some developers believe that it is not a true design pattern, instead, they prefer to call it “MVC architecture.”

Here you separate the user interface logic from the business logic and decouple the major components in such a way that they can be reused efficiently. This approach also promotes parallel development. One of the best rubrics for MVC is “We need SMART models, THIN controllers, and DUMB views.” ( http://wiki.c2.com/?ModelViewController )

Concept

From this introduction, it is apparent that the pattern consists of the three major components: Model, View, and Controller. Controller is placed between View and Model in such a way that Model and View can communicate to each other only through Controller. Here you separate the mechanism of how data is displayed from the mechanism of how the data is manipulated. Figure 26-1 shows a typical MVC architecture.
../images/395506_2_En_26_Chapter/395506_2_En_26_Fig1_HTML.jpg
Figure 26-1

A typical MVC architecture

Key Points to Remember

The following are brief descriptions of the key components in this pattern.
  • View represents the output. It is a presentation layer. Think of it as a user interface/GUI. You can design it with various technologies. For example, in a .NET application, you can use HTML, CSS, WPF, and so forth, and for a Java application, you can use AWT, Swing, JSF, JavaFX, and so forth.

  • Model is the brain of your application. It manages the data and the business logic. It knows how to store and manage (or manipulate) the data, and how to handle the requests that come from controller. But this component is separated from the View component. A typical example is a database, a file system, or similar kinds of storage. It can be designed with JavaBeans, Oracle, SQL Server, DB2, Hadoop, MySQL, and so forth.

  • Controller is the intermediary that accepts users input from the View component and passes the request to the model. When it gets a response from the model, it passes the data to the view. It can be designed with C#.NET, ASP.NET, VB.NET, Core Java, JSP, servlets, PHP, Ruby, Python, and so forth.

There are various implementations of this architecture in different applications. Some of them are as follows:
  • You can have multiple views.

  • Views can pass runtime values (e.g., using JavaScript) to controllers.

  • Your controller can validate the user’s input.

  • Your controller can receive input in various ways. For example, it can get input from a web request via a URL, or you can pass the input by pressing a Submit button on a form.

  • In some applications, Model components can update the View component.

Basically, you need to use this pattern to support your own needs. Figure 26-2, Figure 26-3, and Figure 26-4 show some of the known variations of an MVC architecture.

Variation 1

../images/395506_2_En_26_Chapter/395506_2_En_26_Fig2_HTML.jpg
Figure 26-2

A typical MVC framework

Variation 2

../images/395506_2_En_26_Chapter/395506_2_En_26_Fig3_HTML.jpg
Figure 26-3

A MVC framework with multiple views

Variation 3

../images/395506_2_En_26_Chapter/395506_2_En_26_Fig4_HTML.jpg
Figure 26-4

An MVC pattern implemented with an observer pattern/ event-based mechanism

My favorite description of MVC comes from Connelly Barnes, who states, “An easy way to understand MVC: the model is the data, the view is the window on the screen, and the controller is the glue between the two.” ( http://wiki.c2.com/?ModelViewController )

Real-World Example

Let’s revisit our template method pattern’s real-life example. But this time you interpret it differently. I said that in a restaurant, based on customer input, a chef can vary the taste and make the final products. The customers do not place their orders directly to the chef. The customers see the menu card (view), may consult with the waiter/waitress, and place their order. The waiter/waitress passes the order slip to the chef, who gathers the required materials from the restaurant’s kitchen (similar to storehouses/computer databases). Once prepared, the waiter/waitress carries the plate to the customer’s table. So, you can consider the role of the waiter/waitress as the controller, and the chef with their kitchen as the model (and the food preparation materials as data).

Computer-World Example

Many web programming frameworks uses the concept of MVC framework. Some of the typical example include Django, Ruby on Rails, ASP.NET, and so forth. For example, a typical ASP.NET MVC project has the structure shown in Figure 26-5.
../images/395506_2_En_26_Chapter/395506_2_En_26_Fig5_HTML.jpg
Figure 26-5

A typical MVC structure in a ASP.NET project

But it should be noted that different technologies can follow different structure and so, it is not necessary to get a folder structure with the strict naming convention like this. In the Java world, in a MVC architecture, you may notice the use of Java servlets as controllers and JavaBeans as models, whereas JSPs create different views.

Illustration

Most of the time, you want to use the concept of MVC with technologies that can give you built-in support and that can do a lot of ground work for you. In that case, you may need to learn new terminologies. In Java applications, you may want to use Swing or JavaFX, and so forth, for a better GUI.

Throughout this book, I used a console window to show output from different design pattern implementations. So, let’s continue to use the console window as a view in the upcoming implementation because the focus here is on the MVC structure, not new technologies.

For simplicity and to match our theory, I divided the upcoming implementation into three basic parts: Model, View, and Controller. Once you look at the Package Explorer view, you see that separate packages are created to accomplish this task. Here are some important points.
  • In this application, the requirement is very simple. There are employees who need to register themselves in an application/system. Initially, the application starts with three different registered employees: Amit, Jon, and Sam. At any time, you should be able to see the enrolled employees in the system.

  • You can add a new employee or delete an employee from the registered employees list.

  • A simple check is added in the Employee class to ensure that you are not adding an employee repeatedly in the application.

  • To delete an employee from the registered list, you need to pass the employee ID in the client code, but the application will do nothing if an employee ID is not found in the registered list.

Now go through the implementation and consider the comments for your immediate reference.

Class Diagram

Figure 26-6 shows the class diagram. I omitted the client code dependencies to emphasize the core architecture.
../images/395506_2_En_26_Chapter/395506_2_En_26_Fig6_HTML.png
Figure 26-6

Class diagram

Package Explorer View

Figure 26-7 shows the high-level structure of the program.
../images/395506_2_En_26_Chapter/395506_2_En_26_Fig7_HTML.jpg
Figure 26-7

Package Explorer view

Implementation

Here is the implementation.

//Employee.java
package jdp2e.mvc.model;
//The key "data" in this application
public class Employee
{
    private String empName;
    private String empId;
    public String getEmpName() {
        return empName;
    }
    public String getEmpId() {
        return empId;
    }
    public Employee(String empName, String empId)
    {
        this.empName=empName;
        this.empId=empId;
    }
    @Override
    public String toString()
    {
        return empName + "'s employee id is: "+ empId ;
    }
    @Override
    //To check uniqueness.
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Employee)) return false;
        Employee empObject = (Employee) o;
        if (!empName.equals(empObject.empName)) return false;
        //cannot use the following for an int
        if (!empId.equals(empObject.empId)) return false;
        return true;
    }
}
//Model.java
package jdp2e.mvc.model;
import java.util.List;
//Model interface
public interface Model
{
    List<Employee> getEnrolledEmployeeDetailsFromModel();
    void addEmployeeToModel(Employee employeee);
    void removeEmployeeFromModel(String employeeId);
}
//EmployeeModel.java
package jdp2e.mvc.model;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
//EmployeeModel class
public class EmployeeModel implements Model
{
    List<Employee> enrolledEmployees;
    public EmployeeModel()
    {
        //Adding 3 employees at the beginning.
        enrolledEmployees = new ArrayList<Employee>();
        enrolledEmployees.add(new Employee("Amit","E1"));
        enrolledEmployees.add(new Employee("John","E2"));
        enrolledEmployees.add(new Employee("Sam","E3"));
    }
    public List<Employee> getEnrolledEmployeeDetailsFromModel()
    {
        return enrolledEmployees;
    }
    //Adding an employee to the model(student list)
    @Override
    public void addEmployeeToModel(Employee employee)
    {
        System.out.println(" Trying to add an employee to the registered list.");
        if( !enrolledEmployees.contains(employee))
        {
            enrolledEmployees.add(employee);
            System.out.println(employee+" [added recently.]");
        }
        else
        {
            System.out.println(employee+" is already added in the system.");
        }
    }
    //Removing an employee from model(student list)
    @Override
    public void removeEmployeeFromModel(String employeeId)
    {
        boolean flag=false;
        ListIterator<Employee> employeeIterator=enrolledEmployees.listIterator();
        System.out.println(" Trying to remove an employee from the registered list.");
        while(employeeIterator.hasNext())
        {
            Employee removableEmployee=((Employee)employeeIterator.next());
            if(removableEmployee.getEmpId().equals(employeeId))
            {
                //To avoid ConcurrentModificationException,try to
                //remember to invoke remove() on the iterator but not on
                //the list.
                employeeIterator.remove();
                System.out.println("Employee " + removableEmployee.getEmpName()+ " with id "+ employeeId+" is removed now.");
                flag=true;
            }
        }
        if(flag==false)
        {
            System.out.println("###Employee Id " + employeeId +" Not found.###");
        }
    }
}
//View.java
package jdp2e.mvc.view;
import java.util.List;
import jdp2e.mvc.model.Employee;
public interface View
{
    void showEnrolledEmployees(List<Employee> enrolledEmployees);
}
//ConsoleView.java
package jdp2e.mvc.view;
import java.util.List;
import jdp2e.mvc.model.Employee;
//ConsoleView class
public class ConsoleView implements View
{
    @Override
    public void showEnrolledEmployees(List<Employee> enrolledEmployees)
    {
        System.out.println(" ***This is a console view of currently enrolled employees.*** ");
        for( Employee employee : enrolledEmployees)
        {
            System.out.println(employee);
        }
        System.out.println("---------------------");
    }
}
//Controller.java
package jdp2e.mvc.controller;
import jdp2e.mvc.model.Employee;
//Controller
public interface Controller
{
    void displayEnrolledEmployees();
    void addEmployee(Employee employee);
    void removeEmployee(String employeeId);
}
//EmployeeController.java
package jdp2e.mvc.controller;
import java.util.List;
import jdp2e.mvc.model.*;
import jdp2e.mvc.view.*;
public class EmployeeController implements Controller
{
    private Model model;
    private View  view;
    public EmployeeController(Model model, View view)
    {
        this.model = model;
        this.view = view;
    }
    @Override
    public void displayEnrolledEmployees()
    {
        //Get data from Model
        List<Employee> enrolledEmployees = model.getEnrolledEmployeeDetailsFromModel();
        //Connect to View
        view.showEnrolledEmployees(enrolledEmployees);
    }
    //Sending a request to model to add an employee to the list.
    @Override
    public void addEmployee(Employee employee)
    {
        model.addEmployeeToModel(employee);
    }
    //Sending a request to model to remove an employee from the list.
    @Override
    public void removeEmployee(String employeeId)
    {
        model.removeEmployeeFromModel(employeeId);
    }
}

//Client code

//MVCArchitectureExample.java
package jdp2e.mvc.demo;
import jdp2e.mvc.model.*;
import jdp2e.mvc.view.*;
import jdp2e.mvc.controller.*;
public class MVCArchitectureExample {
    public static void main(String[] args) {
        System.out.println("***MVC architecture Demo*** ");
        //Model
        Model model  = new EmployeeModel();
        //View
        View view = new ConsoleView();
        //Controller
        Controller controller = new EmployeeController(model, view);
        controller.displayEnrolledEmployees();
        //Add an employee
        controller.addEmployee(new Employee("Kevin","E4"));
        controller.displayEnrolledEmployees();
        //Remove an existing employee using the employee id.
        controller.removeEmployee("E2");
        controller.displayEnrolledEmployees();
        //Cannot remove an  employee who does not belong to the list.
        controller.removeEmployee("E5");
        controller.displayEnrolledEmployees();
        //Avoiding duplicate entry
        controller.addEmployee(new Employee("Kevin","E4"));
    }
}

Output

Here is the output.
***MVC architecture Demo***
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
John's employee id is: E2
Sam's employee id is: E3
---------------------
Trying to add an employee to the registered list.
Kevin's employee id is: E4 [added recently.]
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
John's employee id is: E2
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to remove an employee from the registered list.
Employee John with id E2 is removed now.
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to remove an employee from the registered list.
###Employee Id E5 Not found.###
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to add an employee to the registered list.
Kevin's employee id is: E4 is already added in the system.

Q&A Session

  1. 1.

    Suppose you have a programmer, a DBA, and a graphic designer. Can you guess their roles in a MVC architecture?

    The graphic designer designs the view layer. The DBA makes the model and programmer works to make an intelligent controller.

     
  2. 2.
    What are the key advantages of using MVC design patterns?
    • “High cohesion and low coupling” is the slogan of MVC. Tight coupling between model and view is easily removed in this pattern. So, it can be easily extendable and reusable.

    • It supports parallel development.

    • You can also provide multiple runtime views.

     
  3. 3.
    What are the challenges associated with MVC patterns?
    • Requires highly skilled personnel.

    • It may not be suitable for a tiny application.

    • Developers need to be familiar with multiple languages/platforms/technologies.

    • Multiartifact consistency is a big concern because you are separating the overall project into three different parts.

     
  4. 4.

    Can you provide multiple views in this implementation?

    Sure. Let’s add a new view called “Mobile view” in the application. Let’s add this class inside the jdp2e.mvc.view package as follows.
    package jdp2e.mvc.view;
    import java.util.List;
    import jdp2e.mvc.model.Employee;
    //This class is added to discuss a question in "Q&A Session"
    //MobileView class
    public class MobileView implements View
    {
        @Override
        public void showEnrolledEmployees(List<Employee> enrolledEmployees)
        {
            System.out.println(" ***This is a mobile view of currently enrolled employees.*** ");
            System.out.println("Employee Id"+ " "+ " Employee Name");
            System.out.println("______________________");
            for( Employee employee : enrolledEmployees)
            {
                System.out.println(employee.getEmpId() + " "+ employee.getEmpName());
            }
            System.out.println("---------------------");
        }
    }
     
The modified Package Explorer view is similar to Figure 26-8.
../images/395506_2_En_26_Chapter/395506_2_En_26_Fig8_HTML.jpg
Figure 26-8

Modified Package Explorer view

Add the following segment of code at the end of your client code.
//This segment is addeed to discuss a question in "Q&A Session"
view = new MobileView();
controller = new EmployeeController(model, view);
controller.displayEnrolledEmployees();

Now if you run the application, you see the modified output.

Modified Output

Here is the modified output. The last part of your output shows the effect of your new changes. These changes are shown in bold.
***MVC architecture Demo***
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
John's employee id is: E2
Sam's employee id is: E3
---------------------
Trying to add an employee to the registered list.
Kevin's employee id is: E4 [added recently.]
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
John's employee id is: E2
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to remove an employee from the registered list.
Employee John with id E2 is removed now.
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to remove an employee from the registered list.
###Employee Id E5 Not found.###
 ***This is a console view of currently enrolled employees.***
Amit's employee id is: E1
Sam's employee id is: E3
Kevin's employee id is: E4
---------------------
Trying to add an employee to the registered list.
Kevin's employee id is: E4 is already added in the system.
 ***This is a mobile view of currently enrolled employees.***
Employee Id   Employee Name
______________________
E1    Amit
E3    Sam
E4    Kevin
---------------------
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.200.3