singleton là gì

Bài viết này mình sẽ nói về singleton pattern là gì? Những đặc điểm của nó. Cách áp dụng pattern này.

Đặt vấn đề

Ở bài viết này mình sẽ nói về 4 câu hỏi thường gặp với singleton pattern.

  1. Singleton Pattern là gì?
  2. Tại sao cần dùng Singleton Pattern?
  3. Làm thế nào để implement Singleton Pattern?
  4. Có những cách nào để implement Singleton Pattern?

Định nghĩa về Singleton Pattern

Định nghĩa thì nhàm chán, nhưng trước khi tìm hiểu về vấn đề nào đó, chúng ta cần phải tìm hiểu định nghĩa về nó trước.

Singleton là 1 trong 5 design pattern của nhóm Creational Design Pattern.

Single theo định nghĩa tiếng anh, mình xin được sao chép nguyên bản:

Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance”

Nghĩa là, singleton pattern là một pattern khởi tạo mà:

  1. Đảm bảo rằng một class chỉ có duy nhất một instance (khởi tạo).
  2. Và cung cấp một cách toàn cục để truy cấp tới instance đó.

Single này không phải độc thân, đơn độc, mà mỗi thằng sẽ có một instance duy nhất.

Vậy, tại sao chúng ta cần phải sử dụng Single Pattern?

Đa phần các đối tượng trong một ứng dụng đều chịu trách nhiệm cho công việc của chúng, truy xuất dữ liệu tự lưu trữ (self-contained data) và các tham chiếu trong phạm vi của chúng.

Tuy nhiên, nhiều đối tượng có thêm những nhiệm vụ và có ảnh hưởng của nó rộng hơn. Chẳng hạn như quản lý các nguồn tài nguyên bị giới hạn hay là theo dõi toàn bộ trạng thái của hệ thống.

sử dụng Single Pattern
sử dụng Single Pattern

Ví dụ về singleton:

Về một ứng dụng có chức năng bật tắt nhạc nền.

Khi người dùng mở app thì ứng dụng sẽ tự động mở nhạc nền và nếu người dùng muốn tắt thì phải vào setting trong app để tắt nó.

Trong setting của app cho phép người dùng mở hay tắt nhạc, và trong trường hợp này bạn sẽ cần sử dụng singleton để quản lí việc này.

Chắc chắn bạn phải cần duy nhất 1 instance để có thể ra lệnh bật hay tắt. Đơn giản vì bạn không thể tạo 1 instance để mở nhạc rồi sau đó lại tạo 1 instance khác để tắt nhạc. Lúc này sẽ có 2 instance được tạo ra, 2 instance này không liên quan đến nhau nên không thể thực hiện thực hiện việc cho nhau được.

Khi instance nào bật thì chỉ có instance đó mới được phép tắt nên dẫn đến phải cần 1 instance.

Singleton dùng để làm gì?

Vấn đề mà singleton giải quyết là

  • Đảm bảo rằng 1 class chỉ có 1 instance duy nhất và class này luôn sẵn sàng để sử dụng ở bất kỳ thời điểm hoặc vị trí nào trong phần mềm ứng dụng của chúng ta.
  • 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ớn hạn chỉ định.

Mục đích của Singleton Pattern

Một class thuộc dạng Singleton có nghĩa là: nó chỉ có một instance duy nhất, bất kỳ ở đâu đều có thể truy cập tới instance của class singleton đó.

Ưu điểm và khuyết điểm của Singleton Pattern

Về mặt ưu điểm của pattern này đem lại quá rõ ràng:

  • Ai cũng có thể truy cập vào instance của singleton class,  thực hiện gọi nó ở bất cứ đâu.
  • Dữ liệu ứng dụng không thay đổi bởi chỉ có một instance duy nhất.
  • Singleton class có hỗ trợ interface trong khi static class thì lại không. Đây là sự khác biệt giúp chúng ta nhận biết cần phải xác định để tạo static class hay singleton class.
  • Hỗ trợ kế thừa, static class thì không hỗ trợ kế thừa.

Một số nhược điểm của pattern này:

  • Cần phải sử dụng tới keyword trung gian là .instance (có thể cached khi sử dụng tần suất nhiều).
  • Chỉ tạo một instance duy nhất.
  • Làm tăng kết nối giữa các script và điều này thì không tốt, các scripts con phụ thuộc quá nhiều vào các singletons và khi singletons thay đổi có thể gây ra bug hoặc lỗi.
  • Không sử dụng được đa hình.

Cấu trúc pattern này:

cấu trúc singleton
cấu trúc singleton

Để biến một class thành Singleton, cần đảm bảo:

  • Định nghĩa một attribute là private static và đó là thể hiện duy nhất của class này.
  • Định nghĩa public static getInstance() dùng để khởi tạo đối tượng (hàm accessor).
  • Thực hiện lazy-init trong hàm accessor (chỉ khi gọi mới khởi tạo thể hiện).
  • Constructor là private hay protected, vì bạn không muốn client tạo nhiều thể hiện
  • Client chỉ có thể gọi hàm accessor khi muốn có thể hiện của class

Lưu ý

Các design pattern khác có thể dùng cùng với Singleton. Chẳng hạn, Abstract Factory, Builder, Prototype. Các đối tượng Facade và State cũng thường là Singleton.

Không nên hiểu máy móc rằng Singleton nghĩa là tồn tại chính xác 1 thể hiện. Có thể có những thể hiện khác nhau cho những mục đích khác nhau. Đây cũng là ưu điểm của Singleton so với việc dùng biến toàn cục (global variable).

Singleton là toàn cục. Vì vậy, khi đơn giản là muốn truyền một đối tượng A cho đối tượng B xử lý, hãy cân nhắc xem bạn có thật sự cần một đối tượng toàn cục hay không.

Sử dụng Singleton Pattern khi nào?

Một số trường hợp sử dụng của Singleton Pattern thường gặp là:

  • Vì class dùng Singleton chỉ tồn tại 1 Instance nên nó thường được dùng cho các trường hợp giải quyết những bài toán cần truy cập vào các ứng dụng như: Shared resource, Logger, Configuration, Thread pool,..
  • Sử dụng trong một số class của core java như: java.lang.Runtime, java.awt.Desktop.
Factory Pattern là gì

Bài viết này mình sẽ giúp các bạn tìm hiểu thêm về một Design Pattern trong nhóm Creational pattern – Factory Method. Hãy cùng mình tìm hiểu để hiểu thêm về factory pattern design là gì nhé.

Factory Pattern là gì?

Factory Method Design Pattern, hay còn được gọi là Factory Pattern là một trong những Pattern phổ biến trong lập trình hướng đối tượng.
Factory Pattern thuộc nhóm Creational Design Pattern (mẫu khởi tạo). Vì nhiệm vụ của mẫu này là quản lý và trả về các đối tượng theo yêu cầu, cung cấp một trong những cách tốt nhất để tạo một đối tượng. Giúp cho việc khởi tạo đổi tượng một cách linh hoạt hơn.

Factory pattern là một trong những mẫu thiết kế được sử dụng nhiều nhất trong Java.
Trong Factory Pattern, chúng ta tạo đối tượng mà không để lộ logic tạo đối tượng ở phía người dùng và tham chiếu đến đối tượng mới được tạo ra bằng cách sử dụng một interface chung.

Một định nghĩa bằng tiếng anh nguyên bản như sau:

“Factory Method is a creational design pattern that Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.“

Factory Design Pattern có lợi ích gì?

  • Giúp việc khởi tạo các Objects mà che giấu đi xử lí logic của việc khởi tạo đó. Người dùng không biết logic thực sự được khởi tạo bên dưới phương thức factory.
  • Mẫu thiết kế này cho phép các lớp con chọn kiểu đối tượng cần tạo.
  • Nó thúc đẩy sự liên kết lỏng lẻo bằng cách loại bỏ sự cần thiết phải ràng buộc các lớp cụ thể vào code. Nghĩa là code chỉ tương tác với interface hoặc lớp abstract, để nó sẽ làm việc với bất kỳ lớp nào implements interface đó hoặc extends lớp abstract.
  • Factory Pattern giúp giảm sự phụ thuộc giữa các module: cung cấp 1 hướng tiếp cận với Interface thay vì các implement. Giúp chuơng trình độc lập với những lớp cụ thể mà chúng ta cần tạo 1 đối tượng, code ở phía client sẽ không bị ảnh hưởng khi thay đổi logic ở factory hay sub class.
  • Việc mở rộng code dễ dàng hơn: khi cần mở rộng, chỉ việc tạo ra những sub class và implement thêm vào factory method.
  •  Dễ dạng quản lý life cycle của các Object được tạo bởi Factory Method Pattern.
  • Thống nhất về mặt naming convention: giúp cho các developer có thể hiểu về cấu trúc source code.

Áp dụng vào đâu

  • “Factory method” thường được sử dụng trong việc thiết kế toolkit hay framework, đoạn mã của framework cần thiết phải tạo ra một đối tượng là những lớp con tương ứng tăng tính mềm dẻo trong sử dụng framework đó.
  • Cách sử dụng, khi nào bạn nên sử dụng mẫu thiết kế Factory Method

Mẫu thiết kế này sẽ phát huy được ưu điểm của nó trong một số trường hợp sau:

  • Khi bạn chưa biết nên khởi tạo đối tượng mới từ class nào.
  • Khi bạn muốn tập trung các đoạn code liên quan đến việc khởi tạo các đối tượng mới về cùng một nơi để dễ dàng cho những thao tác và xử lý.
  • Khi bạn không muốn người dùng phải biết hết tên của các class có liên quan đến quá trình khởi tạo cũng như muốn che giấu, đóng gói toàn bộ logic của quá trình khởi tạo một đối tượng mới nào đó khỏi phía người dùng.

Ưu điểm và nhược điểm của Factory Method Pattern

Ưu điểm

• Factory Method Pattern giúp hạn chế sự phụ thuộc giữa creator và concrete products.
• Factory Method Pattern giúp gom các đoạn code tạo ra product vào một nơi trong chương trình, nhờ đó giúp dễ theo dõi và thao tác.
• Với Pattern này, chúng ta có thể dễ dàng mở rộng, thêm những đoạn code mới vào chương trình mà không cần phá vỡ các đối tượng ban đầu .

Nhược điểm

Ngoài những ưu điểm nên trên thì mẫu thiết kế này cũng có nhược điểm như sau:
• Mã code có thể trở nên phức tạp hơn mức bình thường do đòi hỏi phải sử dụng nhiều class mới có thể cài đặt được pattern này.

Nên sử dụng Factory Pattern khi nào?

Dựa vào những lợi ích của việc sử dụng Factory pattern mà ta sẽ dùng chúng với một số mục đích sau:
• Khi tạo ra 1 cách mới trong việc khởi tạo Object => Tất nhiên là vậy.
• Che giấu xử lý logic của việc khởi tạo => Trong trường hợp bạn đang muốn viết 1 thư viện để cho người khác sử dụng.
• Giảm bớt sự phụ thuộc => Dễ dàng cho việc mở rộng trong trường hợp bạn chưa biết chắc số lượng các đối tượng là đã đủ cho bài toán của mình chưa.

Mục đích sử dụng

Tại sao chúng ta lại phải dùng Factory pattern thay cho việc khởi tạo đối tượng thông thường? Dùng Factory pattern có lợi ích gì?
Factory pattern đưa ra 1 ý tưởng mới cho việc khởi tạo các instance phù hợp với mỗi yêu cầu từ phía Client. Sử dụng Factory pattern sẽ có những ưu điểm sau:

  • Tạo ra 1 cách mới trong việc khởi tạo Object thông qua 1 interface chung.
  • Khởi tạo các Objects mà che giấu đi xử lí logic của việc khởi tạo đấy.
  • Giảm sự phụ thuộc giữa các module, các logic với các class cụ thể. Mà chỉ phụ thuộc vào interface hoặc abstract class.

Ví dụ mẫu thiết kế Factory Method – trong c# winform

Chúng ta sẽ tạo một thiết kế theo mẫu Factory như hình phí dưới.

sơ đồ factory pattern
sơ đồ factory pattern

Bước 1: Tạo interface Shape.cs

interface trong factory
interface trong factory

Bước 2: Tạo những Class cụ thể implement interface :

Rectangle.cs

Rectangle

Square.cs

Square trong factory pattern

Circle.cs

Circle-factory-pattern
Bước 3: Tạo class Factory để khởi tạo các lớp cụ thể dựa vào thông tin đã cho

ShapeFactory.cs

Factory pattern class

Bước 4:

Factory lấy kết quả
Bước 5: Xuất kết quả

kết quả factory pattern
Kết luận

Trong bài viết này, chúng ta đã cùng nhau tìm hiểu về Factory Pattern là gì, ví dụ cụ thể. Hy vọng pattern này sẽ giúp ích cho các bạn trong tương lai. Mong các bạn để lại những ý kiến để bài viết hoàn thiện hơn nữa.

Tài liệu tham khảo :

https://www.tutorialspoint.com/design_pattern/factory_pattern.htm