Tôi là Brandon Rhodes [trang web, Twitter] và đây là hướng dẫn đang phát triển của tôi về các mẫu thiết kế bằng ngôn ngữ lập trình Python
- Trang web này cho phép tôi thu thập tất cả các ý tưởng của mình về Python và Mẫu thiết kế ở một nơi
- Tôi hy vọng rằng những trang này làm cho các mẫu dễ khám phá hơn — dễ tìm thấy hơn trong các tìm kiếm trên web và dễ đọc hơn — so với khi chúng nằm rải rác trên các video và trang trình bày về các cuộc hội thảo về Python của tôi
- Sức nặng của các nghĩa vụ khác làm cho sự tiến bộ của tôi bị gián đoạn. Để kiểm tra tài liệu mới, chỉ cần truy cập lịch sử cam kết của kho lưu trữ dự án của trang web này trên GitHub, nơi bạn cũng có thể chọn “Xem” để nhận các bản cập nhật
Với những phần sơ bộ đã hoàn tất, đây là các mẫu
nhóm bốn người. Nguyên tắc¶
- Nguyên tắc tổng hợp trên thừa kế
- Vấn đề. vụ nổ phân lớp
- Giải pháp số 1. Mẫu bộ điều hợp
- Giải pháp số 2. Mô hình cây cầu
- Giải pháp số 3. Mẫu trang trí
- Giải pháp số 4. Ngoài các mẫu Gang of Four
- né tránh. câu lệnh “nếu”
- né tránh. Đa thừa kế
- né tránh. hỗn hợp
- né tránh. Xây dựng các lớp động
Các mẫu dành riêng cho Python¶
- Mẫu đối tượng toàn cầu
- Mô hình không đổi
- tính toán thời gian nhập khẩu
- hằng số Dunder
- Mẫu đối tượng toàn cầu
- Các đối tượng toàn cầu có thể thay đổi
- Nhập thời gian I/O
- Mẫu phương pháp giới hạn trước
- lựa chọn thay thế
- hoa văn
- Mẫu đối tượng Sentinel
- Giá trị trọng điểm
- Mẫu con trỏ Null
- Mẫu đối tượng Null
- Đối tượng canh gác
nhóm bốn người. Mẫu sáng tạo¶
- Mô hình nhà máy trừu tượng
- Phương pháp Pythonic. nhà máy gọi được
- Sự hạn chế. ngoài vòng pháp luật vượt qua callables
- Sự hạn chế. vượt qua các lớp học ngoài vòng pháp luật
- khái quát hóa. Nhà máy trừu tượng hoàn chỉnh
- Mẫu xây dựng
- Builder như sự tiện lợi
- sắc thái
- người xây dựng đấu tay đôi
- Một trường hợp thoái hóa. mô phỏng đối số tùy chọn
- Mẫu Phương thức Nhà máy
- né tránh. sử dụng tiêm phụ thuộc
- Thay vì. sử dụng Nhà máy thuộc tính lớp
- Thay vì. sử dụng Instance Attribute Factory
- Thuộc tính sơ thẩm ghi đè thuộc tính lớp
- Bất kỳ cuộc gọi nào được chấp nhận
- Thực thi
- Mẫu nguyên mẫu
- Vấn đề
- giải pháp Pythonic
- Thực thi
- Mẫu Singleton
- định hướng
- Việc thực hiện của Gang of Four
- Một triển khai Pythonic hơn
- bản án
nhóm bốn người. Mô hình kết cấu¶
- Mô hình tổng hợp
- Thí dụ. hệ thống tập tin UNIX
- Trên hệ thống phân cấp
- Thí dụ. Lập trình GUI với Tkinter
- Thực hiện. được thừa kế hay không?
- Mẫu trang trí
- Sự định nghĩa
- Thực thi. trình bao bọc tĩnh
- Thực thi. bọc chiến thuật
- Thực thi. trình bao bọc động
- báo trước. Gói không thực sự hoạt động
- Gian lận. Khỉ vá từng đối tượng
- Gian lận. Khỉ vá lớp
- Đọc thêm
- Mô hình Flyweight
- Nhà máy hoặc Nhà xây dựng
- Thực thi
nhóm bốn người. Mẫu hành vi¶
- Mẫu Iterator
- Lặp lại với vòng lặp “for”
- hoa văn. iterable và iterator của nó
- Một vòng xoắn. các đối tượng là iterator của riêng chúng
- Triển khai Iterable và Iterator
- Mức độ định hướng bổ sung của Python
Thư mục¶
- Cuốn sách Băng nhóm bốn người
- Tái cấu trúc bởi Martin Fowler
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ó bằng 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 Đóng Mở [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ĩaclass 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 liên kết 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']
4class 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 Đóng Mở [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ể đang được người dùng khác sử dụng, 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']
03. Nguyên tắc thay thế Liskov [LSP]
Nguyên tắc thay thế của Liskov nói 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']
03class 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']
4Thay đổ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ọngclass 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. 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']
90class 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']
25. 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 nhauclass 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']
9Từ đâ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']
0Thậ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óaclass 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']
3kế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