À ờ, vấn đề design pattern (DP) là một câu chuyện khá là nhức nhối ở tất cả các ngôn ngữ lập trình, lý thuyết của DP thì dù được dịch sang tiếng việt nhưng cũng rất khó hiểu và gây hoang mang cho người đọc (vì DP là thứ dùng rồi thì mới hiểu, không dùng cần hiểu làm chi…). Mình đã research khá nhiều trên google về design pattern nhưng nhận về chủ yếu là lý thuyết, vì vậy từ hôm nay mình quyết định bắt đầu viết về DP với vai trò của người đã trải nghiệm.

Design Pattern đầu tiên là Singleton

Lý thuyết:

Theo cuốn Gang of Four của mấy ông gì gì đấy ở nước ngoài, design pattern gồm có 3 loại

  1. Creational – Khởi tạo
  2. Structure – Cấu trúc
  3. Behavior – Hành vi

Tạm nhớ thế đã, ở đây đang nói đến Singleton thì thằng Singleton thuộc nhóm Creational – Khởi tạo.

Khi nào dùng đến:

  • Đảm bảo rằng một class chỉ có duy nhất một instance
  • Cần một cách toàn cầu để truy cấp tới instance đó.

WTF, instance là cái quái gì, nhớ lại kiến thức OOP, có thể tưởng tượng rằng, đầu tiên ta khởi tạo 1 class tên Student, class này có các thuộc tính là tên thằng student, tuổi và học lực của nó. Thông thường chúng ta sẽ tạo class khi cần có nhu cầu tạo và quản lý rất nhiều thằng Student cùng lúc (1 trường học sẽ có nhiều Student, ví dụ thế). Nhưng Singleton sinh ra để class Student chỉ được phép tạo ra đúng 1 và chỉ 1 thằng student, lại WTF lần nữa.

Tại sao khi tạo class mà chỉ cho phép tạo 1 đối tượng của class đó

Trong thực tế, có nhiều trường hợp phải sử dụng class mà chỉ có 1 đối tượng, ví dụ nhé, nhà trường cần phải làm việc với ngân hàng để vay vốn (1 – vay vốn) mua bàn ghế or khi phụ huynh nộp đủ tiền cho nhà trường thì nhà trường chuyển lại tiền đã vay cho ngân hàng (2 – trả lãi). Vì là trường công nghệ nên nhà trường tạo 1 class ke_toan để quản lý các kế toán, tuy nhiên vì trường rất bé nên hiệu trưởng chỉ được phép tuyển 1 kế toán và cô kế toán này sẽ là người chuyên đi làm việc với ngân hàng. Khi tuyển về cô lên ngân hàng lấy 1 giấy đảm bảo rằng khi nhà trường muốn giao dịch với ngân hàng thì chỉ có thể qua cô này, kể cả khi nhà trường muốn làm những giao dịch khác (3 – gửi tiết kiệm) với ngân hàng thì tất cả mọi việc chỉ cần gọi đến cô kế toán là xong. Những đầu việc 1,2,3 gọi là hành vi của đối tượng trong class.

Rồi, làm thế nào để tạo Singleton

Nghĩ thế này cho dễ, đầu tiên khi tạo class ke_toan, nhà trường check xem có kế toán nào tồn tại chưa, nếu chưa thì tạo mới/tuyển về 1 kế toán (khởi tạo instance), trong quá trình khởi tạo, cô kế toán lên ngân hàng để lấy giấy đảm bảo nhà trường muốn giao dịch với ngân hàng thì chỉ có thể qua tôi.

Vậy làm thế nào để đảm bảo trường chỉ có 1 kế toán, giờ có 1 người lấy được giấy đảm bảo của cô kế toán, mang về lên ngân hàng để giao dịch thì làm thế nào. Đáp án là nhà trường cần giữ bí mật chuyện kế toán lên ngân hàng lấy giấy đảm bảo (giữ private hàm khởi tạo), mỗi khi ai có việc gì cần ngân hàng thì gọi cô kế toán ra giải quyết, vậy là xong (tạo hàm get_instance để gọi kế toán)

Bắt tay vào code

class KeToan():
    __instance = None

    @staticmethod       # giữ static hàm get_instance
    def get_instance():
        if not KeToan.__instance:               # nếu không có kế toán
            KeToan.__instance = KeToan          # tạo ra 1 kế toán => khởi tạo ở hàm __init__
        return KeToan.__instance                # trả về cô kế toán

    def __init__(self):
        self.name = 'Co Ke Toan'
        self.key = self.len_ngan_hang_lay_key() # hành động lên NH lấy key

    def len_ngan_hang_lay_key(self):
        return '121331'

    def vay_von(self):
        '''
        Len NH vay von
        '''
        pass

    def tra_lai(self):
        '''
        Len NH tra lai
        '''
        pass

    def gui_tiet_kiem(self, so_tien):
        '''
        Len NH tra lai
        '''
        pass

Như vậy mỗi khi có việc gì cần làm việc với ngân hàng ta chỉ cần gọi:

co_ke_toan = KeToan().get_instance()
co_ke_toan.gui_tiet_kiem(so_tien=10000000)  # gửi tiết kiệm 10tr VNĐ