Ví dụ Callback trong JAVA

Ngày đăng: 24/07/2020   -    Cập nhật: 01/08/2020
Trong khi học hay làm việc với lập trình, đôi khi, có rất nhiều thứ chúng ta vô tình sử dụng mà không hiểu về nó.

Trong số đó, Callback cũng được nhiều người dùng mà có khi không biết nó là gì. Hôm nay, hãy thử xem ví dụ Callback trong Java để hiểu hơn về một trong những khái niệm như vậy.


Vậy...

1. Callback trong Java là gì?


“Trong lập trình máy tính, callback là một đoạn code chạy được (thường là một phương thức A) được sử dụng như tham số truyền vào của phương thức B nào đó.

Khi phương thức B được gọi. Lập tức (hoặc trễ hơn một chút) phương thức A được gọi.

Các ngôn ngữ lập trình khác nhau hỗ trợ callback theo các cách khác nhau, thường được triển khai dưới dạng chương trình con, phương thức ẩn danh, chuỗi lệnh hoặc con trỏ hàm.”
- Theo Wikipedia.

Bạn nào thích thì xem lại trên wiki, mình đọc cũng không hiểu lắm :D.

Callback trong Java

Callback trong Java

Thế nên mình sẽ định nghĩa lại cho dễ hiểu nhé!
 
  • Thường thì khi thiết kế một hàm, phương thức thì chúng ta có thể sẽ truyền vào một tham số gì đó đúng không nào?
  • Và thường thì tham số đó là gì nhỉ, à thường thì sẽ là một biến với một kiểu dữ liệu nào đó đúng không nào? 
  • Nhưng thay vì một biến, thì lần này chúng ta sẽ truyền vào cả một phương thức vào trong đó luôn.
  • Việc này giúp chúng ta có thể vừa thực hiện một việc trong khi đang thực hiện một việc khác (Synchronous callback)
  • Hoặc “cài cắm” một phương thức để thông báo kết quả của một tác vụ nào đó (Asynchronous callback).
  • Đó, callback trong Java cũng đơn giản như vậy đó.

Đối với các bạn, dễ hiểu hơn hay khó hiểu hơn Wiki thì mình không rõ lắm, riêng mình thì mình thấy khái niệm lại kiểu này dễ hiểu hơn nhiều vì nó cho mình biết chính xác mình cần làm gì để tạo ra callback.

> Bạn nào muốn học lập trình Java bài bản thì tham khảo ngay KHÓA HỌC JAVA (Full Stack) này nhé.

Giờ thì đi vào ví dụ và ứng dụng thực tế của callback thôi nào!


2. Ví dụ đơn giản sử dụng callback trong Java


Các bạn đã bao giờ thiết kế giao diện và phải bắt sự kiện để xử lý chưa?

Nếu đã làm rồi thì các bạn đã sử dụng callback mà không hề hay biết đấy.

Việc bắt sự kiện chương trình trong Java là một ví dụ điển hình trong việc sử dụng callback, làm sao mà chương trình biết khi nào thì người dùng ấn cái này, kéo cái kia, thả cái nọ?

Đó là nhờ callback đã được cài cắm vào hệ điều hành để làm “mật thám” (nó là cái listener đó) có nhiệm vụ theo dõi thông tin, khi nào thì sự kiện muốn bắt xảy ra.

Khi mà sự kiện đó xảy ra thì anh “mật thám” callback này sẽ trả về một giá trị để thông báo cho chương trình biết là người dùng (hay nói chính xác hơn là hệ điều hành) vừa thực hiện thao tác đó.

Chúng ta sẽ đi vào ví dụ bằng code trong việc sử dụng callback trong việc bắt và xử lý sự kiện trong Java (trong ví dụ này mình sử dụng Netbeans để demo)

> Bạn nào chưa biết sử dụng NetBeans thì cài đặt NetBeans và tìm hiểu thêm cách sử dụng cơ bản tại bài viết Thiết kế giao diện trong Java với NetBeans

Mình sẽ cố viết rõ ràng và dễ hiểu cũng như comment có tâm để mọi người có thể hiểu tường tận được vấn đề.


  • Bạn có thể copy code nguyên si mình của mình về chạy thử mà không cần phải thiết kế lại luôn nhé.

Trước tiên là một ví dụ “gần gũi” hơn để hiểu về callback:


Tìm hiểu Callback trong Java thông qua ví dụ thám tử tư

Tìm hiểu Callback trong Java thông qua ví dụ thám tử tư
 

Tình huống:
 
  • Bạn là một người chồng phải đi làm nuôi con, và nghi ngờ con vợ có bồ nhí, giờ không thể bỏ việc mà đi theo rình, nên bạn quyết định sẽ cài thám tử, khi nào con vợ vào khách sạn thì thằng thám tử nó gọi báo cho mình. =)) (Hơi muộn nhỉ nhưng mà kệ đi)

Đầu tiên, ta sẽ tạo lớp SuKien để chứa những sự kiện xảy ra với bà vợ:


class SuKien
{
   public boolean vaoKhachSan = true;
}
 

Tạo một interface ThamTu để chắc chắn rằng thằng thám tử nào cũng phải gọi cho thằng chồng báo cáo kết quả, còn báo cáo kết quả gì và như thế nào thì tùy nhiệm vụ mỗi thằng.


interface ThamTu
{
   void goiChoThangChong();
}
 

Tạo một lớp ThamTuTu để thể hiện cho thám tử tư nhân chuyên dùng để theo dõi các hoạt động liên quan đến đời sống cá nhân.


class ThamTuTu implements ThamTu
{
   private  SuKien suKien = new SuKien();

   public ThamTuTu(){}

   public void goiChoThangChong()
   {
      //kiểm tra sự kiện
      if(suKien.vaoKhachSan)
      {
         System.out.println(
            "Đại bàng gọi thợ săn,
            thỏ con chui vào hang.
            Mang gậy tới mần thịt nhé."
         );
      }
   }
}
 

Tạo ra một lớp Chong để lưu trữ các thuộc tính và hành động của người chồng.


class Chong
{
   public void caiThamTu(ThamTu thamTu)
   {
      thamTu.goiChoThangChong();
   }

   public void diLamKiemTien(){}

   public static void main(String[] args)
   {
      Chong chong = new Chong();
      ThamTu conan = new ThamTuTu();
      chong.caiThamTu(conan); // cài thám tử theo dõi và gọi về cho mình
      chong.diLamKiemTien(); // tiếp tục đi làm kiếm tiền nuôi con
   }
}
 

Bạn có thể hiểu luồng đơn giản của chương trình callback này như sau:

  • Ông chồng cài thám tử.
  • Khi gọi phương thức chong.caiThamTu(conan) (truyền đối tượng conan vào phương thức caiThamTu). Phương thức này sẽ gọi đến phương thức goiChoThangChong() 
  • Sau đó, trong phương thức goiChoThangChong() nó kiểm tra sự kiện vaoKhachSan, nếu true thì gọi báo cáo. Nếu false thì nó không làm gì cả.
Cách sử dụng callback trong Java rất đơn giải phải không?

Như bạn đã thấy,

Bản chất Phương thức CallBack là một hàm được truyền vào một hàm khác dưới dạng đối số và dự kiến ​​sẽ thực thi sau một số loại sự kiện.

Mục đích của 
Phương thức Callback là thông báo cho lớp Sync / Async nếu một số công việc trong lớp khác được thực hiện.

Điều này rất hữu ích khi làm việc với các tác vụ không đồng bộ.

Giả sử,

Chúng ta muốn thực hiện một số tác vụ thông thường như:


  • Thực hiện một số thao tác hoặc hiển thị nội dung sau khi nhấp vào nút hoặc tìm nạp dữ liệu từ internet.

Điều này cũng được sử dụng trong xử lý sự kiện, vì chúng ta nhận được thông báo khi nhấp vào nút thông qua phương thức callback.

Kiểu mẫu thiết kế này được sử dụng trong Observer Design Pattern.

Observer Design Pattern là mẫu thiết kế phần mềm trong đó:


  • Một đối tượng, được gọi là chủ thể, duy trì một danh sách phụ thuộc của nó => được gọi là quan sát viên.
  • Nó tự động thông báo cho chúng về bất kỳ thay đổi trạng thái nào, thường là bằng cách gọi một trong những phương thức của chúng.

Trong Java, Callbacks có thể được thực hiện bằng giao diện. Các thủ tục chung để thực hiện được đưa ra dưới đây.

  • Bước #1: Định nghĩa các phương thức trong một interface mà chúng ta muốn gọi sau callback.
  • Bước #2. Định nghĩa một lớp sẽ triển khai các phương thức callback của interface.
  • Bước #3. Định nghĩa một tham chiếu trong lớp khác để đăng ký callback interface.
  • Bước #4. Sử dụng tham chiếu đó để gọi phương thức callback.

3. Synchronous Callback trong Java


Một cuộc gọi đồng bộ (Synchronous Call) trong Java sẽ chặn hoặc chờ sự kiện trước khi tiếp tục.

Cho đến khi sự kiện của bạn trả về phản hồi, chương trình của bạn sẽ không thực hiện thêm gì nữa.

Vấn đề với các Synchronous Callback trong Java (
cuộc gọi lại đồng bộ) là chúng có độ trễ.

Dưới đây là các bước thực hiện đơn giản của nguyên tắc này:



// Hướng dẫn sử dụng Synchoronous Callback trong Java
// Bước 1: Định nghĩa các phương thức trong một interface
// mà chúng ta muốn gọi sau callback
interface LangNgheSuKien {

    //Bạn có thể tạo bất kỳ phương thức nào
    void lamGiDo();
}
 

Sau đó, ta tạo class A khai triển interface LangNgheSuKien


// Bước 2: Định nghĩa một lớp sẽ triển khai các phương
// thức callback của interface.

class A implements LangNgheSuKien {

    @Override
    public void lamGiDo()
    {
        System.out.println("Thực hiện Callback sau tác vụ đồng bộ");
        // perform some routine operation
    }
    // Một số phương thức khác của class A 
}
 

Tiếp theo,


// Bước 3: Định nghĩa một tham chiếu trong lớp khác để
// đăng ký callback interface.
class B {

    private LangNgheSuKien nTrinhNghe;

    // Thiết lập trình lắng nghe
    public void dangKyLangNgheSuKien(LangNgheSuKien nTrinhNghe)
    {
        this.nTrinhNghe = nTrinhNghe;
    }

    // Tác vụ đồng bộ
    public void lamTacVuDongBo()
    {

        // Thực hiện bất kỳ thao tác nào
        System.out.println("Thực hiện Callback trước tác vụ đồng bộ");

        // Kiểm tra nếu trình nghe đã được đăng ký.
        if (this.nTrinhNghe != null) {

            // Thực thi phương thức Callback của lớp A
            nTrinhNghe.lamGiDo();
        }
    }
}
 


Cuối cùng,



// Bước 4: Sử dụng tham chiếu để gọi phương thức Callback
public class Main {
    public static void main(String[] args
    { 
        B obj = new B();
        LangNgheSuKien nTrinhNghe = new A();
        obj.dangKyLangNgheSuKien(nTrinhNghe);
        obj.lamTacVuDongBo();
    }
}
 

Kết quả khi chạy chương trình là:


Thực hiện Callback trước tác vụ đồng bộ
Thực hiện Callback sau tác vụ đồng bộ
 

4. Asynchronous Callback trong Java


Một cuộc gọi không đồng bộ (Asynchronous Call) không chặn chương trình thực thi.

Khi cuộc gọi trả về từ sự kiện, cuộc gọi sẽ quay trở lại phương thức callback.

Vì vậy, trong ngữ cảnh của Java, chúng ta phải tạo một luồng mới và gọi phương thức callback bên trong luồng đó.

Phương thức callback có thể được gọi từ một luồng nhưng không phải là một yêu cầu.

Một Callback cũng có thể bắt đầu một luồng mới, do đó làm cho chúng không đồng bộ.

> Tìm hiểu thêm về Lập trình đa luồng trong Java

Ví dụ dưới đây là các bước thực hiện đơn giản của nguyên tắc này:

Bước #1:



interface LangNgheSuKien {

   // Bạn có thể tạo bất kỳ phương thức nào
   void lamGiDo();
}
 

Bước #2:


class A implements LangNgheSuKien {

   @Override
   public void lamGiDo()
   {
      System.out.println("Thực hiện Callback sau tác vụ không đồng bộ"); 
      // Thực hiện một số thao tác thông thường khác 
   }
   // Một vài phương thức khác 
}
 

Bước #3:


class B { 

   private LangNgheSuKien nTrinhNghe;

   // Thiết lập trình nghe
   public void dangKyLangNgheSuKien(LangNgheSuKien nTrinhNghe
   { 
      this.nTrinhNghe = nTrinhNghe; 
   } 

   // Tác vụ không đồng bộ
   public void lamTacVuKhongDongBo() 
   { 

      // Một tác vụ không đồng bộ luôn được thực thi trong
      // một luồng mới
      new Thread(new Runnable() {
         public void run()
         { 

            // Thực thi bất kỳ hàng động nào đó
            System.out.println("Thực hiện hành động trong tác vụ không đồng bộ");

            // Kiểm tra nếu trình nghe đã được đăng ký
            if (nTrinhNghe != null) {

               // Thực thi phương thức Callback của lớp A
               nTrinhNghe.lamGiDo();
            }
         }
      }).start();
   }
}
 

Bước #4:


public class Main {
   public static void main(String[] args
   { 
      B obj = new B(); 
      LangNgheSuKien nTrinhNghe = new A(); 
      obj.dangKyLangNgheSuKien(nTrinhNghe); 
      obj.lamTacVuKhongDongBo();
   }
}
 

Khi chạy chương trình chúng ta có kết quả như sau:


Thực hiện hành động trong tác vụ không đồng bộ
Thực hiện Callback trong tác vụ không đồng bộ
 

Câu hỏi: Khi nào nên sử dụng Synchronous Callback trong Java?


Khi lập trình Java, bất kỳ quá trình nào có nhiều tác vụ trong đó các tác vụ phải được thực hiện theo trình tự và không chiếm nhiều thời gian thì nên sử dụng Synchronous Callback.

Ví dụ: Khi chuyển khoản tiền qua ứng dụng ngân hàng, hệ thống sẽ gửi mã OTP ngay sau khi bạn đồng ý chuyển khoản (Nếu bạn không đồng ý, tác vụ gửi mã OTP sẽ không được thực hiện)


Câu hỏi: Khi nào nên sử dụng Asynchronous Callback trong Java?


Khi các tác vụ không phụ thuộc vào nhau và có thể mất một thời gian để thực thi chúng, chúng ta nên sử dụng Asynchronous Callback.

Kết luận


Chúng ta vừa cùng nhau đi qua về callback trong Java, callback thường xuyên được sử dụng trong nhiều chương trình khác nhau cũng như nhiều ngôn ngữ khác nhau.

Callback là một thủ thuật rất hay giúp chúng ta linh hoạt hơn trong quá trình xử lý chương trình.

> Tham khảo: Callback trong JavaScript.

Tuy nhiên hãy cẩn thận với nó, vì việc làm dụng callback có thể sẽ dẫn tới callback hell làm “nát bét” cái chương trình của bạn vì chúng nó sẽ chồng chéo lên nhau rất khủng khiếp.

Đến đây thôi, bài viết cũng đã khá dài rồi, tôi mong rằng bài viết sẽ giúp ích gì đó cho các bạn trong quá trình TỰ HỌC JAVA. Hãy nhớ luyện tập mỗi ngày một ít nhé.

“Đi đi, chậm cũng được, miễn là đừng dừng lại”.


---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543 - 0353655150 
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python

Bình luận Facebook
Khóa học liên quan đến bài viết

Khóa học PHP Full stack [2023] cho người mới bắt đầu

96 giờ
Khóa học Lập trình PHP Full stack, phiên bản cập nhật lần thứ 8. Dạy Lập trình PHP bài bản từ Front end đến Back end + Laravel. Hướng dẫn làm 2 Dự Án Web lớn

KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG

50 giờ
Khóa học giúp học viên sử dụng thành thạo ngôn ngữ Lập trình Python (3x). Hiểu và phát triển được Ứng dụng Web với Django Framework. Học thực hành với Giảng viên cao cấp.

Lập trình PHP với Laravel Framework

42 giờ
Khóa học Lập trình PHP với Laravel Framework được NIIT - ICT HÀ NỘI xây dựng nhằm hoàn thiện kỹ năng lập trình web các các bạn đã biết Lập trình Web PHP thuần.

Khóa học Java Full stack (IJFD)

104 giờ
Học lập trình Java Fullstack với khóa học được xây dựng theo lộ trình bài bản, từ JAVA CƠ BẢN đến JAVA WEB và nâng cao về JAVA FRAMEWORK như: Spring Boot, Hibernate
Mục lục
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!