Phần 1 trước, Cafedev đã giới thiệu khá chi tiết về observer pattern, Bài này chúng ta sẽ tiến hành thực hành nó với code cụ thể. Ace có thể tham khảo các bài khác tại series Design Pattern tại đây.
Giả sử chúng ta đang xây dựng một ứng dụng thông báo cricket cho người xem về các thông tin như điểm số hiện tại, tỷ lệ chạy, v.v. Giả sử chúng ta đã tạo hai phần tử hiển thị là CurrentScoreDisplay và AverageScoreDisplay. CricketData có tất cả dữ liệu (chạy, điểm, v.v.) và bất cứ khi nào dữ liệu thay đổi, các phần tử hiển thị sẽ được thông báo với dữ liệu mới và chúng hiển thị dữ liệu mới nhất tương ứng
Áp dụng Observer pattern cho vấn đề trên:
Hãy để chúng ta xem cách chúng ta có thể cải thiện thiết kế ứng dụng của mình bằng cách sử dụng Observer pattern. Nếu chúng ta quan sát luồng dữ liệu, chúng ta có thể dễ dàng thấy rằng CricketData và các phần tử hiển thị tuân theo mối quan hệ chủ thể(subject)-người quan sát(observers).
Sơ đồ lớp mới:
Triển khai bằng code Java:
// Java program to demonstrate working of
// onserver pattern
import java.util.ArrayList;
import java.util.Iterator;
// Implemented by Cricket data to communicate
// with observers
interface Subject
{
public void registerObserver(Observer o);
public void unregisterObserver(Observer o);
public void notifyObservers();
}
class CricketData implements Subject
{
int runs;
int wickets;
float overs;
ArrayList<Observer> observerList;
public CricketData() {
observerList = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
observerList.add(o);
}
@Override
public void unregisterObserver(Observer o) {
observerList.remove(observerList.indexOf(o));
}
@Override
public void notifyObservers()
{
for (Iterator<Observer> it =
observerList.iterator(); it.hasNext();)
{
Observer o = it.next();
o.update(runs,wickets,overs);
}
}
// get latest runs from stadium
private int getLatestRuns()
{
// return 90 for simplicity
return 90;
}
// get latest wickets from stadium
private int getLatestWickets()
{
// return 2 for simplicity
return 2;
}
// get latest overs from stadium
private float getLatestOvers()
{
// return 90 for simplicity
return (float)10.2;
}
// This method is used update displays
// when data changes
public void dataChanged()
{
//get latest data
runs = getLatestRuns();
wickets = getLatestWickets();
overs = getLatestOvers();
notifyObservers();
}
}
// This interface is implemented by all those
// classes that are to be updated whenever there
// is an update from CricketData
interface Observer
{
public void update(int runs, int wickets,
float overs);
}
class AverageScoreDisplay implements Observer
{
private float runRate;
private int predictedScore;
public void update(int runs, int wickets,
float overs)
{
this.runRate =(float)runs/overs;
this.predictedScore = (int)(this.runRate * 50);
display();
}
public void display()
{
System.out.println("\nAverage Score Display: \n"
+ "Run Rate: " + runRate +
"\nPredictedScore: " +
predictedScore);
}
}
class CurrentScoreDisplay implements Observer
{
private int runs, wickets;
private float overs;
public void update(int runs, int wickets,
float overs)
{
this.runs = runs;
this.wickets = wickets;
this.overs = overs;
display();
}
public void display()
{
System.out.println("\nCurrent Score Display:\n"
+ "Runs: " + runs +
"\nWickets:" + wickets +
"\nOvers: " + overs );
}
}
// Driver Class
class Main
{
public static void main(String args[])
{
// create objects for testing
AverageScoreDisplay averageScoreDisplay =
new AverageScoreDisplay();
CurrentScoreDisplay currentScoreDisplay =
new CurrentScoreDisplay();
// pass the displays to Cricket data
CricketData cricketData = new CricketData();
// register display elements
cricketData.registerObserver(averageScoreDisplay);
cricketData.registerObserver(currentScoreDisplay);
// in real app you would have some logic to
// call this function when data changes
cricketData.dataChanged();
//remove an observer
cricketData.unregisterObserver(averageScoreDisplay);
// now only currentScoreDisplay gets the
// notification
cricketData.dataChanged();
}
}
Đầu ra:
Average Score Display:
Run Rate: 8.823529
PredictedScore: 441
Current Score Display:
Runs: 90
Wickets:2
Overs: 10.2
Current Score Display:
Runs: 90
Wickets:2
Overs: 10.2
Lưu ý: Bây giờ chúng ta có thể thêm / xóa bao nhiêu người quan sát(observers) mà không cần thay đổi đối tượng cũng được
Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.
Tài liệu từ cafedev:
- Full series tự học Design Pattern từ cơ bản tới nâng cao tại đây nha.
- Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!