Tổng quan về Singleton Design Pattern


Singleton đảm bảo một class chỉ có duy nhất một instance được khởi tạo và nó cung cấp phương thức truy cập đến instance đó từ mọi nơi (global access).  


I. Giới thiệu

Singleton là một trong số 5 design patterns thuộc nhóm Creational Design Pattern - nhóm hỗ trợ khởi tạo class. Nó đảm bảo một class chỉ có duy nhất một instance được khởi tạo và nó cung cấp phương thức truy cập đến instance đó từ mọi nơi (global access).

 

Sử dụng Singleton khi chúng ta muốn:

  • Đảm bảo rằng chỉ có một instance của lớp.
  • Việc quản lý việc truy cập tốt hơn vì chỉ có một thể hiện duy nhất.
  • Có thể quản lý số lượng thể hiện của một lớp trong giới hạn chỉ định.

II. Mục đích ra đời

Đôi khi, trong quá trình phân tích thiết kế một hệ thống, chúng ta mong muốn có những đối tượng cần tồn tại duy nhất và có thể truy xuất mọi lúc mọi nơi. Vậy làm thế nào để hiện thực được một đối tượng như thế khi xây dựng mã nguồn? Chúng ta có thể nghĩ tới việc sử dụng một biến toàn cục (global variable : public static final). Tuy nhiên, việc sử dụng biến toàn cục nó phá vỡ quy tắc đóng gói của Lập trình hướng đối tượng.

 

Để giải bài toán trên, người ta hướng đến một giải pháp là sử dụng Singleton pattern.

III. Kiến trúc

 

Cách sử dụng

  • Đặt constructor là private để client không thể khởi tạo object của class
  • Tạo một biến static private là instance của class đó để đảm bảo rằng nó là duy nhất và chỉ được tạo ra trong class đó thôi
  • Tạo một public static method trả về instance vừa khởi tạo bên trên, đây là cách duy nhất để các class khác có thể truy cập vào instance của class này

IV. Ưu & nhược điểm

    1. Ưu điểm

  • Có thể chắc chắn rằng một lớp chỉ có một instance
  • Có khả năng truy cập đến instance từ mọi nơi (global access)
  • Đối tượng singleton chỉ được khởi tạo duy nhất một lần khi nó được yêu cầu lần đầu.
  • Kiểm soát truy cập đến instance duy nhất
  • Giảm namespace

    2. Nhược điểm

  • Vi phạm Single Responsibility Principle. Mẫu này giải quyết hay vấn đề trên cùng một thời điểm.
  • Singleton pattern có thể thể hiện thiết kế kém (bad design), chẳng hạn, khi các thành phần của chương trình biết quá nhiều về nhau.
  • Có thể sinh ra khó khăn trong việc unit test client code của Singleton bởi nhiều test frameworks dựa vào kế thừa khi sản sinh mock objects.

V. Khi nào thì sử dụng

Singleton được sử dụng khi:

  • Có thể chắc chắn rằng một lớp chỉ có một instance
  • Có khả năng truy cập đến instance từ mọi nơi (global access)
  • Đối tượng singleton chỉ được khởi tạo duy nhất một lần khi nó được yêu cầu lần đầu.
  • Vì class dùng Singleton chỉ tồn tại 1 Instance (thể hiện) nên nó thường được dùng cho các trường hợp giải quyết các bài toán cần truy cập vào các ứng dụng như: Shared resource, Logger, Configuration, Caching, Thread pool, …
  • Một số design pattern khác cũng sử dụng Singleton để triển khai: Abstract Factory, Builder, Prototype, Facade,…

VI. Source code minh họa với C#

    1. Tạo class Singleton

    public class Singleton
    {
        private int index;
        private static readonly object lockObject = new object();
        private static volatile Singleton uniqueInstance;

        private Singleton(int index)
        {
            this.index = index;
        }

        public static Singleton GetInstance()
        {
            if(uniqueInstance == null)
            {
                lock (lockObject)
                {
                    if (uniqueInstance == null)
                    {
                        var random = new Random();

                        uniqueInstance = new Singleton(random.Next(1, 4));
                    }
                }
            }
            return uniqueInstance;
        }

        public void SaysHi()
        {
            Console.WriteLine("Hello everyone, I am Dev number " + index);
        }
    }

    2. Sử dụng

    class Program
    {
        static void Main(string[] args)
        {
            var thread1 = new Thread(() => Singleton.GetInstance().SaysHi());
            var thread2 = new Thread(() => Singleton.GetInstance().SaysHi());

            thread1.Start();
            thread2.Start();
        }
    }

Tài liệu tham khảo

[1] Refactoring.Guru

[2] Design Patterns for Dummies, Steve Holzner, PhD

[3] Head First, Eric Freeman

[4] Gang of Four Design Patterns 4.0

[5] Dive into Design Pattern

Chia sẽ bài viết :