Singleton design pattern
在某些時候, 為了管控資源或是避免多個物件分享相同資源造成的 Race condition, 我們希望在同一時間, 某個類別只會存在一個唯一的物件, 此時就可以利用這個設計模式.
當系統中某項資源只有一個, 而且絕對獨一無二時, 最適合使用這個Pattern, 也就是說使用這個Pattern可以確保 物件個體只有一個, 不會因programmer的疏忽而產生兩個或兩個以上
public class Singleton{ private static Singleton uniqueInstance; private Singleton(){}//使用Private建構子, 確保外界無法new出物件 public static synchronized Singleton getInstance() { // 使用 synchronized 關鍵字避免同時兩支Thread 進入函數 if(uniqueInstance == null ) {uniqueInstance = new Singleton();} return uniqueInstance; } }
物件組合設計 – use composition
組合物件通常有 “has a” 的關係. 真實世界中, 輪子, 方向盤, 變速箱, 引擎等獨立物件並沒有任何功能. 但車子組合了這些物件而產生了功用.
程式語言中, 物件是一種資料型態, 此資料型態就區分為組合型或非組合型.
與組合型態不同的是子型態(Subtyping), 比如汽車是一種運輸工具. 子型態不描述每個物件之間的關係, 但相對的, 具有 “is a” 的關係
為了彈性及日後容易修改, 應該著重在 composition的設計上, 而不是在繼承.
繼承測試
public class Airplane { public void startEngine() { // ... } public void fly() { // ... } } public class Cessna extends Airplane { public void setTurboMode(boolean b) { // ... } }
組合測試
public class FlyBehaviour { public void fly() { // ... } } public class Airplane { @Resource FlyBehaviour fb; public void fly() { fb.fly(); } public void startEngine() { // ... } } public class Bird { @Resource FlyBehaviour fb; public void fly() { fb.fly(); } public void tweet() { // ... } }
將FlyBehaviour 拆開成獨立的類別或介面, 再由其他的類別組合進去, 就變成了 has a 的關係
DAO 設計模組 (Data Access Object)
DAO模組是用來分離低階資料存取及高階商業服務
1. DAO介面 – 此介面定義模型物件執行時的標準操作.
2. DAO具体類別 – 此類別實作上述的介面. 負責從資料來源取得資料. 資料來源包含xml 及其他儲存裝置.
3. Model Object or Value Object – 簡易的POJO物件, 包含了 get/set的方法, 存取資料.
Model Object通常是資料本身, 具簡易的方式取得內部的資訊. 而DAO類別則是交給使用者操作的sdk, 裏面有存取, 新增, 刪除Model Object的方法.
使用DAO類別時, 通常都是要生成物件的. 而物件參考, 都會使用介面參考, 不是DAO類別的參考.
Implementation
底下將建立Student物件作為模型物件. StudentDao是一個介面, StudentDaoImpl則是實作了介面的實体類別. DaoPatternDemo為執行程式.
Step 1
Create Value Object.
Student.java
public class Student { private String name; private int rollNo; Student(String name, int rollNo){ this.name = name; this.rollNo = rollNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getRollNo() { return rollNo; } public void setRollNo(int rollNo) { this.rollNo = rollNo; } }
Step 2
Create Data Access Object Interface.
StudentDao.java
import java.util.List; public interface StudentDao { public List<Student> getAllStudents(); public Student getStudent(int rollNo); public void updateStudent(Student student); public void deleteStudent(Student student); }
Step 3
Create concrete class implementing above interface.
StudentDaoImpl.java
import java.util.ArrayList; import java.util.List; public class StudentDaoImpl implements StudentDao { //list is working as a database List<Student> students; public StudentDaoImpl(){ students = new ArrayList<Student>(); Student student1 = new Student("Robert",0); Student student2 = new Student("John",1); students.add(student1); students.add(student2); } @Override public void deleteStudent(Student student) { students.remove(student.getRollNo()); System.out.println("Student: Roll No " + student.getRollNo() + ", deleted from database"); } //retrive list of students from the database @Override public List<Student> getAllStudents() { return students; } @Override public Student getStudent(int rollNo) { return students.get(rollNo); } @Override public void updateStudent(Student student) { students.get(student.getRollNo()).setName(student.getName()); System.out.println("Student: Roll No " + student.getRollNo() + ", updated in the database"); } }
Step 4
Use the StudentDao to demonstrate Data Access Object pattern usage.
DaoPatternDemo.java
public class DaoPatternDemo { public static void main(String[] args) { StudentDao studentDao = new StudentDaoImpl(); //print all students for (Student student : studentDao.getAllStudents()) { System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]"); } //update student Student student =studentDao.getAllStudents().get(0); student.setName("Michael"); studentDao.updateStudent(student); //get the student studentDao.getStudent(0); System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]"); } }
Step 5
Verify the output.
Student: [RollNo : 0, Name : Robert ] Student: [RollNo : 1, Name : John ] Student: Roll No 0, updated in the database Student: [RollNo : 0, Name : Michael ]