Nguyên tắc thay thế Liskov Ví dụ về Python

Trong lĩnh vực lập trình hướng đối tượng và thiết kế phần mềm, các nguyên tắc SOLID là một bộ 5 nguyên tắc tạo điều kiện thuận lợi cho việc kiểm tra, bảo trì và khả năng đọc mã. Lợi ích của một nhóm áp dụng các nguyên tắc này trong quá trình phát triển mã của họ bao gồm triển khai phần mềm nhanh hơn, tăng khả năng sử dụng lại mã và khả năng mở rộng cũng như cải thiện gỡ lỗi. Những nguyên tắc này là một tập hợp con của những nguyên tắc được nêu bởi Robert C. Martin, được gọi là chú Bob, trong bài viết Nguyên tắc thiết kế và mẫu thiết kế của mình

SOLID là từ viết tắt dễ nhớ đề cập đến từng nguyên tắc bằng từ viết tắt của nó trong tiếng Anh. Những từ viết tắt này là

  • Nguyên tắc trách nhiệm duy nhất [SRP]
  • Nguyên tắc Mở-Đóng [OCP]
  • Nguyên tắc thay thế Liskov [LSP]
  • Nguyên tắc phân tách giao diện [ISP]
  • Nguyên tắc đảo ngược phụ thuộc [DIP]

Các nguyên tắc SOLID là một trong những nguyên tắc được biết đến nhiều nhất trong thế giới thiết kế phần mềm và là cơ sở tốt để phát triển mã trong môi trường cộng tác, chẳng hạn như trong lĩnh vực kỹ thuật dữ liệu. Tại Damavis, chúng tôi muốn áp dụng các phương pháp lập trình tốt này để cung cấp phần mềm chất lượng cho khách hàng của mình. Tiếp theo, các nguyên tắc SOLID được minh họa từng cái một với một số ví dụ đơn giản được viết bằng Python

1. Nguyên tắc trách nhiệm duy nhất [SRP]

Nguyên tắc đầu tiên của SOLID được gọi là Nguyên tắc Trách nhiệm Đơn nói rằng một lớp chỉ chịu trách nhiệm cho một chức năng. Nói cách khác, lớp chỉ nên có một lý do duy nhất để thay đổi. Trong ví dụ đơn giản sau đây, một lớp

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4 với 5 phương thức khác nhau được định nghĩa

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

    def greet[self, duck2: Duck]:
        print[f"{self.name}: {self.do_sound[]}, hello {duck2.name}"]

Chức năng chính của lớp này là định nghĩa một con vịt. Nếu định nghĩa này cần được thay đổi, lớp này sẽ được thay đổi. Vấn đề nằm ở phương thức

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
0 chịu trách nhiệm cho việc có thể nói chuyện với những con vịt khác. Nếu bạn muốn thay đổi chức năng của cuộc trò chuyện giữa những con vịt, bạn cũng sẽ thay đổi lớp
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4, tôi. e. , sẽ có thêm lý do để thay đổi lớp học. Hậu quả của việc không tôn trọng nguyên tắc này có thể là một số, chẳng hạn như làm cho việc gỡ lỗi trở nên khó khăn hơn, vì một số lỗi chỉ đến cùng một vị trí và các chức năng được kết hợp chặt chẽ hơn

Để giải quyết vấn đề này trong trường hợp của ví dụ, một lớp

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
2 mới được định nghĩa đảm nhận tất cả các chức năng giao tiếp. Lớp mới này cho phép một cuộc trò chuyện giữa hai con vịt, nơi chúng chào nhau. Bằng cách này, chức năng giao tiếp đã được thay đổi mà không ảnh hưởng đến lớp
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']

2. Nguyên tắc Mở-Đóng [OCP]

Nguyên tắc Mở/Đóng chỉ ra rằng các lớp nên được mở để mở rộng, nhưng đóng để sửa đổi. Nói cách khác, mã phải được viết theo cách sao cho khi thêm chức năng mới, mã đã viết trước đó, có thể được sử dụng bởi những người dùng khác, sẽ không bị sửa đổi

Trong ví dụ trước, không thể mở rộng chức năng

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
2 để thêm các loại hội thoại khác mà không sửa đổi phương thức
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
5. Để thực hiện nguyên tắc thứ hai, một lớp
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
6 được tạo sẽ chịu trách nhiệm xác định các loại hội thoại khác nhau trong các lớp con của nó với việc triển khai
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
7. Theo cách này, phương pháp
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
5 của
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
2 sẽ chỉ được sử dụng để thực hiện giao tiếp thông qua một kênh và sẽ không bao giờ phải sửa đổi kênh đó [đây là phương pháp cuối cùng]

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
0

3. Nguyên tắc thay thế Liskov [LSP]

Nguyên tắc thay thế của Liskov phát biểu rằng các lớp nên được thay thế bằng các thể hiện của các lớp con của chúng. Để minh họa nguyên tắc này, chúng tôi xem xét khả năng các loài chim mới có thể được thêm vào trong tương lai. Để đạt được điều này, một cách thực hành tốt là thêm lớp trừu tượng

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00 và để các loài chim như
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4 thực hiện các phương thức của nó. Từ đây cũng có thể định nghĩa, từ
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00, một lớp con của
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
03

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4

Thay đổi nhỏ này đã tạo ra một vấn đề. các phương pháp của

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
04 phụ thuộc vào
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4. Điều này có nghĩa là lớp này không thể chấp nhận, ví dụ, các thể hiện của lớp
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
03. Do đó, sự phụ thuộc vào
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4 phải được thay đổi thành
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00. Sau khi thực hiện thay đổi này,
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00 có thể được thay thế bằng bất kỳ thể hiện nào của các lớp con của nó mà không gây ra bất kỳ vấn đề nào, nghĩa là nguyên tắc thứ ba đang được tôn trọng

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
9

4. Nguyên tắc phân tách giao diện [ISP]

Nguyên tắc Phân tách Giao diện nói rằng các máy khách không nên bị buộc phải dựa vào các phương thức mà chúng không sử dụng và do đó đề xuất tạo các giao diện hoặc lớp cụ thể cho các máy khách đó. Trong phần trước, một lớp mới

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
03 đã được thêm vào mô tả một con quạ. Nhưng có một vấn đề trong định nghĩa đó. con quạ không biết bơi và lớp trừu tượng
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00 buộc chúng ta phải định nghĩa
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
42

Để giải quyết vấn đề này, lớp

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00 phải được tách riêng. Để làm như vậy, hai lớp trừu tượng mới được xác định cho những con chim có thể bơi
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
44 và những con có thể bay [
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
45], sẽ mở rộng chức năng của
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
00. Do đó,
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
03 thực hiện chức năng của
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
45 và
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
4 thực hiện chức năng của
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
90 và
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
45. Bây giờ, nếu loài chim cánh cụt biết bơi nhưng không biết bay được triển khai, thì chỉ nên mở rộng
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
90

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
2

5. Nguyên tắc đảo ngược phụ thuộc [DIP]

Nguyên tắc cuối cùng được gọi là Nguyên tắc đảo ngược phụ thuộc có thể được tách thành hai câu. Một mặt, nó chỉ ra rằng trừu tượng không nên phụ thuộc vào chi tiết, vì chi tiết nên phụ thuộc vào trừu tượng. Mặt khác, nó chỉ ra rằng các lớp cấp cao không nên phụ thuộc vào các lớp cấp thấp, vì cả hai nên phụ thuộc vào sự trừu tượng. Tóm lại, trừu tượng nên phụ thuộc vào trừu tượng

Để minh họa cho nguyên tắc này, người ta quyết định rằng kênh hiện được xác định trong lớp giao tiếp sẽ có nhiều chức năng hơn trong tương lai. Theo nguyên tắc đầu tiên [SRP], trách nhiệm mới này được trích xuất từ ​​​​lớp

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
2 và được gán cho một lớp trừu tượng mới
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
94. Ngoài ra, lớp giao tiếp hiện được tạo trừu tượng [
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
95] để nó xác định một kênh cụ thể. Sự trừu tượng hóa mới này và phương pháp cuối cùng
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
96 trong
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
94 giúp chúng tôi thực hiện nguyên tắc thứ hai [OCP] vì
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
5 sẽ không cần phải sửa đổi để sử dụng các kênh khác nhau

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
9

Từ đây, một kênh và một bộ giao tiếp có thể được xác định để những chú chim thông minh của chúng ta có thể gửi tin nhắn SMS cho nhau

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
0

Thật không may, việc triển khai này không tôn trọng Nguyên tắc đảo ngược phụ thuộc. Điều này là do bên trong

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
99 bạn đang gọi
class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
20, nghĩa là bạn phụ thuộc vào chi tiết chứ không phải lớp trừu tượng. Để giải quyết vấn đề này, một trình giao tiếp được xác định phụ thuộc trực tiếp vào sự trừu tượng hóa

class Duck:
   
    def __init__[self, name]:
        self.name = name
   
    def fly[self]:
        print[f"{self.name} is flying not very high"]

    def swim[self]:
        print[f"{self.name} swims in the lake and quacks"]

    def do_sound[self] -> str:
        return "Quack"

class Communicator:

    def __init__[self, channel]:
        self.channel = channel

    def communicate[self, duck1 : Duck, duck2: Duck]:
        sentence1 = f"{duck1.name}: {duck1.do_sound[]}, hello {duck2.name}"
        sentence2 = f"{duck2.name}: {duck2.do_sound[]}, hello {duck1.name}"
        conversation = [sentence1, sentence2]
        print[*conversation,
              f"[via {self.channel}]",
              sep = '\n']
3

kết luận

Chúng tôi hy vọng rằng những ví dụ này hữu ích để hiểu những điều cơ bản của nguyên tắc SOLID. Nhờ những thực hành tốt này, bạn có được mã sạch hơn và có thể tái sử dụng, có thể rất hữu ích khi các đồng nghiệp khác nhau phát triển các phần khác nhau của phần mềm hoặc sẽ làm việc trên phần mềm đó trong tương lai

Nguyên tắc thay thế Liskov trong Python là gì?

Nguyên tắc thay thế Liskov được định nghĩa chính thức là. Cho ϕ[x] là một thuộc tính chứng minh được về các đối tượng x thuộc loại T. Vậy thì ϕ[y] phải đúng với các đối tượng y thuộc loại S trong đó S là một kiểu con của T . Nguồn. Barbara Liskov.

Ví dụ về Nguyên tắc thay thế Liskov là gì?

Nói một cách đơn giản, Nguyên tắc thay thế Liskov [LSP] phát biểu rằng các đối tượng của một lớp cha có thể được thay thế bằng các đối tượng của các lớp con của nó mà không làm hỏng ứng dụng. In other words, what we want is to have the objects of our subclasses behaving the same way as the objects of our superclass.

Ví dụ chính xác nhất về Nguyên tắc thay thế Liskov là gì?

Một ví dụ điển hình ở đây là một con chim và một con chim cánh cụt; . Dưới đây là đoạn mã Java hiển thị một ví dụ vi phạm nguyên tắc LSP. Ở đây Bồ câu bay được vì nó là Chim. Trong sự thừa kế này, về mặt kỹ thuật, chim cánh cụt là một con chim, chim cánh cụt không bay. . The below is a Java code snippet showing an example that violates the LSP principle. Here, the Dove can fly because it is a Bird. In this inheritance, much as technically a penguin is a bird, penguins do not fly.

Điều gì vi phạm Nguyên tắc thay thế Liskov?

Một vi phạm rất phổ biến đối với nguyên tắc này là việc triển khai một phần giao diện hoặc chức năng của lớp cơ sở , khiến các phương thức hoặc thuộc tính chưa được triển khai đưa ra ngoại lệ . g. NotImplementedException].

Chủ Đề