Nội dung
Prototype là một mẫu thiết kế khởi tạo cho phép sao chép các đối tượng, ngay cả những đối tượng phức tạp, mà không cần ghép nối với các lớp cụ thể của chúng.
Tất cả các lớp prototype phải có một giao diện chung để có thể sao chép các đối tượng ngay cả khi các lớp cụ thể của chúng là không xác định. Các đối tượng prototype có thể tạo ra các bản sao đầy đủ vì các đối tượng của cùng một lớp có thể truy cập vào các trường riêng tư của nhau.
Cách sử dụng mẫu
Sử dụng: Mẫu Prototype có sẵn trong Python với giao diện có thể sao chép Cloneable
.
Nhận biết: Prototype có thể dễ dàng nhận ra bằng phương thức clone
hoặc copy
, v.v.
Chương trình minh họa
Ví dụ này minh họa cấu trúc của mẫu thiết kế Prototype. Nó tập trung vào việc trả lời những câu hỏi sau:
- Nó bao gồm những lớp nào?
- Các lớp này có vai trò gì?
- Các thành phần của mẫu có liên quan với nhau theo cách nào?
main.py
import copy
class SelfReferencingEntity:
def __init__(self):
self.parent = None
def set_parent(self, parent):
self.parent = parent
class SomeComponent:
"""
Python cung cấp giao diện Prototype của riêng nó thông qua các hàm
'copy.copy' và 'copy.deepcopy'. Và bất kỳ lớp nào muốn triển khai các
tùy chỉnh phải ghi đè các hàm thành viên '__copy__' và '__deepcopy__'.
"""
def __init__(self, some_int, some_list_of_objects, some_circular_ref):
self.some_int = some_int
self.some_list_of_objects = some_list_of_objects
self.some_circular_ref = some_circular_ref
def __copy__(self):
"""
Tạo một bản sao nông. Phương thức này sẽ được gọi bất cứ khi nào
ai đó gọi 'copy.copy' với đối tượng này và giá trị được trả về dưới
dạng bản sao nông mới.
"""
# Đầu tiên, hãy tạo bản sao của các đối tượng lồng nhau.
some_list_of_objects = copy.copy(self.some_list_of_objects)
some_circular_ref = copy.copy(self.some_circular_ref)
# Sau đó, hãy nhân bản chính đối tượng, sử dụng các bản sao
# được chuẩn bị của các đối tượng lồng nhau.
new = self.__class__(
self.some_int, some_list_of_objects, some_circular_ref
)
new.__dict__.update(self.__dict__)
return new
def __deepcopy__(self, memo={}):
"""
Tạo một bản sao sâu. Phương thức này sẽ được gọi bất cứ khi nào ai đó gọi
'copy.deepcopy' với đối tượng này và giá trị trả về được trả về dưới dạng bản
sao sâu mới.
Việc sử dụng đối số 'memo' là gì? Memo là từ điển được thư viện 'deepcopy'
sử dụng để ngăn các bản sao đệ quy vô hạn trong các trường hợp tham chiếu
vòng tròn. Truyền nó cho tất cả các lệnh gọi 'deepcopy' bạn thực hiện trong
quá trình triển khai '__deepcopy__' để ngăn việc đệ quy vô hạn.
"""
# Đầu tiên, hãy tạo bản sao của các đối tượng lồng nhau.
some_list_of_objects = copy.deepcopy(self.some_list_of_objects, memo)
some_circular_ref = copy.deepcopy(self.some_circular_ref, memo)
# Sau đó, hãy nhân bản chính đối tượng, sử dụng các bản sao
# được chuẩn bị của các đối tượng lồng nhau.
new = self.__class__(
self.some_int, some_list_of_objects, some_circular_ref
)
new.__dict__ = copy.deepcopy(self.__dict__, memo)
return new
if __name__ == "__main__":
list_of_objects = [1, {1, 2, 3}, [1, 2, 3]]
circular_ref = SelfReferencingEntity()
component = SomeComponent(23, list_of_objects, circular_ref)
circular_ref.set_parent(component)
shallow_copied_component = copy.copy(component)
# Hãy thay đổi danh sách trong shallow_copied_component và xem
# nó có thay đổi trong component hay không.
shallow_copied_component.some_list_of_objects.append("another object")
if component.some_list_of_objects[-1] == "another object":
print(
"Adding elements to shallow_copied_component's "
"some_list_of_objects adds it to component's "
"some_list_of_objects."
)
else:
print(
"Adding elements to shallow_copied_component's "
"some_list_of_objects doesn't add it to component's "
"some_list_of_objects."
)
# Hãy thay đổi tập hợp trong danh sách các đối tượng.
component.some_list_of_objects[1].add(4)
if 4 in shallow_copied_component.some_list_of_objects[1]:
print(
"Changing objects in the component's some_list_of_objects "
"changes that object in shallow_copied_component's "
"some_list_of_objects."
)
else:
print(
"Changing objects in the component's some_list_of_objects "
"doesn't change that object in shallow_copied_component's "
"some_list_of_objects."
)
deep_copied_component = copy.deepcopy(component)
# Hãy thay đổi danh sách trong deep_copied_component và xem
# nó có thay đổi trong component hay không.
deep_copied_component.some_list_of_objects.append("one more object")
if component.some_list_of_objects[-1] == "one more object":
print(
"Adding elements to deep_copied_component's "
"some_list_of_objects adds it to component's "
"some_list_of_objects."
)
else:
print(
"Adding elements to deep_copied_component's "
"some_list_of_objects doesn't add it to component's "
"some_list_of_objects."
)
# Hãy thay đổi tập hợp trong danh sách các đối tượng.
component.some_list_of_objects[1].add(10)
if 10 in deep_copied_component.some_list_of_objects[1]:
print(
"Changing objects in the component's some_list_of_objects "
"changes that object in deep_copied_component's "
"some_list_of_objects."
)
else:
print(
"Changing objects in the component's some_list_of_objects "
"doesn't change that object in deep_copied_component's "
"some_list_of_objects."
)
print(
f"id(deep_copied_component.some_circular_ref.parent): "
f"{id(deep_copied_component.some_circular_ref.parent)}"
)
print(
f"id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): "
f"{id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent)}"
)
print(
"^^ This shows that deepcopied objects contain same reference, they "
"are not cloned repeatedly."
)
Kết quả:
Adding elements to shallow_copied_component's some_list_of_objects adds it to component's some_list_of_objects.
Changing objects in the component's some_list_of_objects changes that object in shallow_copied_component's some_list_of_objects.
Adding elements to deep_copied_component's some_list_of_objects doesn't add it to component's some_list_of_objects.
Changing objects in the component's some_list_of_objects doesn't change that object in deep_copied_component's some_list_of_objects.
id(deep_copied_component.some_circular_ref.parent): 4429472784
id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): 4429472784
^^ This shows that deepcopied objects contain same reference, they are not cloned repeatedly.
Để lại một bình luận