diff --git a/README.md b/README.md index 2d6d3456a..d06ca1dca 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,12 @@ Presentation Tier patterns are the top-most level of the application, this is co * [Model-View-Presenter](#model-view-presenter) +### Architectual Patterns + +An architectural pattern is a general, reusable solution to a commonly occurring problem in software architecture within a given context. + +* [Data Access Object](#dao) + ### Idioms A programming idiom is a means of expressing a recurring construct in one or more programming languages. Generally speaking, a programming idiom is an expression of a simple task, algorithm, or data structure that is not a built-in feature in the programming language being used, or, conversely, the use of an unusual or notable feature that is built into a programming language. What distinguishes idioms from patterns is generally the size, the idioms tend to be something small while the patterns are larger. @@ -402,6 +408,15 @@ A programming idiom is a means of expressing a recurring construct in one or mor * when you want to improve the "Separation of Concerns" principle in presentation logic * when a user interface development and testing is necessary. +## Data Access Object [↑](#list-of-design-patterns) +**Intent:** Object provides an abstract interface to some type of database or other persistence mechanism. + +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/dao/etc/dao.png "Data Access Object") + +**Applicability:** Use the Data Access Object in any of the following situations +* when you want to consolidate how the data layer is accessed +* when you want to avoid writing multiple data retrieval/persistence layers + ## Double Checked Locking [↑](#list-of-design-patterns) **Intent:** Reduce the overhead of acquiring a lock by first testing the locking criterion (the "lock hint") without actually acquiring the lock. Only if the locking criterion check indicates that locking is required does the actual locking logic proceed. diff --git a/dao/etc/dao.png b/dao/etc/dao.png new file mode 100644 index 000000000..9fe34b976 Binary files /dev/null and b/dao/etc/dao.png differ diff --git a/dao/etc/dao.ucls b/dao/etc/dao.ucls new file mode 100644 index 000000000..bf11f18b3 --- /dev/null +++ b/dao/etc/dao.ucls @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dao/pom.xml b/dao/pom.xml new file mode 100644 index 000000000..e7c9e44ed --- /dev/null +++ b/dao/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.0-SNAPSHOT + + dao + + + junit + junit + test + + + diff --git a/dao/src/main/java/com/iluwatar/App.java b/dao/src/main/java/com/iluwatar/App.java new file mode 100644 index 000000000..878f7b5bf --- /dev/null +++ b/dao/src/main/java/com/iluwatar/App.java @@ -0,0 +1,47 @@ +package com.iluwatar; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without directly + * interacting with the data directly. The below example demonstrates basic operations: select, add, update, and delete. + */ +public class App { + + public static void main(String[] args) { + + CustomerDaoImpl customerDao = new CustomerDaoImpl(generateSampleCustomers()); + + System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + System.out.println("customerDao.getCusterById(2): " + customerDao.getCusterById(2)); + + Customer customer = new Customer(4, "Dan", "Danson"); + customerDao.addCustomer(customer); + + System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + + customer.setFirstName("Daniel"); + customer.setLastName("Danielson"); + customerDao.updateCustomer(customer); + + System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + + customerDao.deleteCustomer(customer); + + System.out.println("customerDao.getAllCustomers(): " + customerDao.getAllCustomers()); + } + + public static List generateSampleCustomers() { + Customer customer1 = new Customer(1, "Adam", "Adamson"); + Customer customer2 = new Customer(2, "Bob", "Bobson"); + Customer customer3 = new Customer(3, "Carl", "Carlson"); + + List customers = new ArrayList(); + customers.add(customer1); + customers.add(customer2); + customers.add(customer3); + return customers; + } +} diff --git a/dao/src/main/java/com/iluwatar/Customer.java b/dao/src/main/java/com/iluwatar/Customer.java new file mode 100644 index 000000000..d3f892cab --- /dev/null +++ b/dao/src/main/java/com/iluwatar/Customer.java @@ -0,0 +1,64 @@ +package com.iluwatar; + +public class Customer { + private int id; + private String firstName; + private String lastName; + + public Customer(int id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return "Customer{" + + "id=" + id + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Customer customer = (Customer) o; + + if (id != customer.id) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id; + return result; + } +} \ No newline at end of file diff --git a/dao/src/main/java/com/iluwatar/CustomerDao.java b/dao/src/main/java/com/iluwatar/CustomerDao.java new file mode 100644 index 000000000..0c4cf2155 --- /dev/null +++ b/dao/src/main/java/com/iluwatar/CustomerDao.java @@ -0,0 +1,11 @@ +package com.iluwatar; + +import java.util.List; + +public interface CustomerDao { + public List getAllCustomers(); + public Customer getCusterById(int id); + public void addCustomer(Customer customer); + public void updateCustomer(Customer customer); + public void deleteCustomer(Customer customer); +} \ No newline at end of file diff --git a/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java b/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java new file mode 100644 index 000000000..d2069d672 --- /dev/null +++ b/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java @@ -0,0 +1,55 @@ +package com.iluwatar; + +import java.util.List; + +/** + * The data access object (DAO) is an object that provides an abstract interface to some type of database or other persistence mechanism. + * By mapping application calls to the persistence layer, DAO provide some specific data operations without exposing details of the database. + * This isolation supports the Single responsibility principle. It separates what data accesses the application needs, in terms of + * domain-specific objects and data types (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS, + * database schema, etc. + */ +public class CustomerDaoImpl implements CustomerDao { + + // Represents the DB structure for our example so we don't have to managed it ourselves + // Note: Normally this would be in the form of an actual database and not part of the Dao Impl. + private List customers; + + public CustomerDaoImpl(List customers) { + this.customers = customers; + } + + @Override + public List getAllCustomers() { + return customers; + } + + @Override + public Customer getCusterById(int id) { + for (int i = 0; i < customers.size(); i++) { + if (customers.get(i).getId() == id) { + return customers.get(i); + } + } + // No customer found + return null; + } + + @Override + public void addCustomer(Customer customer) { + customers.add(customer); + } + + + @Override + public void updateCustomer(Customer customer) { + if (customers.contains(customer)) { + customers.set(customers.indexOf(customer), customer); + } + } + + @Override + public void deleteCustomer(Customer customer) { + customers.remove(customer); + } +} \ No newline at end of file diff --git a/dao/src/test/java/com/iluwatar/AppTest.java b/dao/src/test/java/com/iluwatar/AppTest.java new file mode 100644 index 000000000..89b9e61d8 --- /dev/null +++ b/dao/src/test/java/com/iluwatar/AppTest.java @@ -0,0 +1,12 @@ +package com.iluwatar; + +import org.junit.Test; + +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/pom.xml b/pom.xml index 33b34296f..6510a457e 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ adapter bridge composite + dao decorator facade flyweight