Nguyên lý Low Coupling trong GRASP Pattern

nguyen-ly-low-coupling-trong-grasp-pattern

1. Nguyên lý Low Coupling là gì?

  • Coupling là thước đo mức độ phụ thuộc của một lớp vào các lớp khác. Khớp nối cao dẫn đến mã khó thay đổi hoặc duy trì một mã duy nhất để thay đổi thành chỉ một mã class có thể dẫn đến những thay đổi lan tỏa khắp hệ thống.

  • Low Coupling là một nguyên tắc thiết kế phần mềm quan trọng, nhằm giảm thiểu sự phụ thuộc lẫn nhau giữa các module hoặc lớp trong một hệ thống. Mục tiêu của Low coupling là để tạo ra một hệthống mà trong đó các phần tử riêng lẻ có thể thay đổi mà không ảnh hưởng đến các phần tử khác.

  • Hãy xem xét ví dụ sau:
    Hệ thống gửi tin nhắn có hai loại là SMS và Email:

    • SMS: Gửi tin nhắn qua điện thoại.
    • Email: Gửi email đến người dùng.
  • Cần thiết kế sao cho hệ thống dễ mở rộng (thêm các loại tin nhắn khác) và đạt Low Coupling.

  • Dưới đây là triển khai code bằng ngôn ngữ lập trình Java với High Coupling:

// Lớp gửi SMS
class SMSMessage {
    public void sendSMS(String recipient, String content) {
        System.out.println("Sending SMS to " + recipient + ": " + content);
    }
}

// Lớp gửi Email
class EmailMessage {
    public void sendEmail(String recipient, String content) {
        System.out.println("Sending Email to " + recipient + ": " + content);
    }
}

// Lớp MessageService
class MessageService {
    private SMSMessage smsMessage = new SMSMessage();
    private EmailMessage emailMessage = new EmailMessage();

    public void sendSMS(String recipient, String content) {
        smsMessage.sendSMS(recipient, content);
    }

    public void sendEmail(String recipient, String content) {
        emailMessage.sendEmail(recipient, content);
    }
}

// Main sử dụng MessageService
public class Main {
    public static void main(String[] args) {
        MessageService service = new MessageService();

        // Gửi SMS
        service.sendSMS("1234567890", "Hello via SMS!");

        // Gửi Email
        service.sendEmail("user@example.com", "Hello via Email!");
    }
}
  • Giải thích đoạn code trên:

    • Class SMSMessage thực hiện gửi tin nhắn thông SMS.
    • Class EmailMessage thực hiện gửi tin nhắn thông qua Email.
    • Class MessageService thực hiện tạo các đối tượng từ SMSMessage, EmailMessage và tạo 2 phương thức gửi Message tương ứng.
    • Class Main chứa phương thức main thực hiện tạo đối tượng từ MessageService và thực hiện 2 phương thức gửi Message.
  • Dễ thấy vấn đề gặp phải với High Coupling:

    • Sự phụ thuộc cao:
    • MessageService phụ thuộc trực tiếp vào các lớp SMSMessageEmailMessage.
    • Nếu thêm loại tin nhắn mới (ví dụ: Push Notification), phải sửa đổi MessageService.
    • Khó mở rộng: Khi thêm loại tin nhắn, phải thay đổi mã nguồn của MessageService, vi phạm nguyên tắc Open/Closed.
    • Khó kiểm thử: Không thể kiểm thử MessageService độc lập mà không cần đến các lớp SMSMessage hoặc EmailMessage.
    • Không linh hoạt: MessageService bị ràng buộc chặt chẽ với cách triển khai của từng loại tin nhắn.
  • Cách giải quyết:

    • Dependency Injection: Các module không giao tiếp trực tiếp với nhau, mà thông qua interface. Module cấp thấp sẽ implement interface, module cấp cao sẽ gọi module cấp thấp thông qua interface. Dưới đây là code sau khi áp dụng Dependency Injection:
// Interface chung cho các loại Message
interface Message {
    void send(String recipient, String content);
}

// Lớp thực hiện gửi SMS
class SMSMessage implements Message {
    @Override
    public void send(String recipient, String content) {
        System.out.println("Sending SMS to " + recipient + ": " + content);
    }
}

// Lớp thực hiện gửi Email
class EmailMessage implements Message {
    @Override
    public void send(String recipient, String content) {
        System.out.println("Sending Email to " + recipient + ": " + content);
    }
}

// Lớp sử dụng Message
class MessageService {
    private Message message;

    public MessageService(Message message) {
        this.message = message;
    }

    public void sendMessage(String recipient, String content) {
        message.send(recipient, content);
    }
}

public class Main {
    public static void main(String[] args) {
        // Gửi SMS
        Message sms = new SMSMessage();
        MessageService smsService = new MessageService(sms);
        smsService.sendMessage("1234567890", "Hello via SMS!");

        // Gửi Email
        Message email = new EmailMessage();
        MessageService emailService = new MessageService(email);
        emailService.sendMessage("user@example.com", "Hello via Email!");
    }
}
  • Trong đoạn code trên, ta sẽ sử dụng tạo một interface Message chứa phương thức trừu tượng là sendMessage. Hai class SMSMessageEmailMessage sẽ implements interface MessageOverride lại phương thức sendMessage sao cho phù hợp với mục đích của từng class.

  • Class MessageService sẽ đảm nhận việc thực thi phương thức gửi tin nhắn, nhưng ở đây sẽ không sử dụng SMSMessageEmailMessage để khởi tạo trực tiếp đối tượng mà sẽ dùng interface Message là thuộc tính trong MessageService. Tại sao? Bởi vì interface cho phép chúng ta áp dụng tính đa hình trong OOP.

  • Trong Class Main, phương thức Main sẽ lần lượt thực hiện:

    • Tạo đối tượng sms từ Class SMSMessage.
    • Tạo đối tượng smsService từ Class MessageService.
    • Đối tượng smsService gọi thực hiện phương thức sendMessage.
    • Tạo đối tượng email từ Class EmailMessage.
    • Tạo đối tượng emailService từ Class MessageService.
    • Đối tượng emailService gọi thực hiện phương thức sendMessage.
  • Dễ thấy, chúng ta có thể dễ dàng tùy biến loại Message mà đối tượng được tạo từ MessageService sẽ thực thi, từ đó dễ dàng thêm các loại Message khác.

2. Lợi ích của nguyên lý Low Coupling

3. Kết luận:

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
nondestructive-testing-for-additive-manufacturing

Nondestructive Testing for Additive Manufacturing

Next Post
validating-thermography-system-performance

Validating Thermography System Performance

Related Posts