Tôi nghĩ rằng cách phổ biến nhất để thêm một cái gì đó vào bộ sưu tập là sử dụng một số Add
phương thức mà bộ sưu tập cung cấp:
class Item {}
var items = new List<Item>();
items.Add(new Item());
và thực sự không có gì bất thường về điều đó.
Tuy nhiên, tôi tự hỏi tại sao chúng ta không làm theo cách này:
var item = new Item();
item.AddTo(items);
phương pháp đầu tiên có vẻ tự nhiên hơn . Điều này sẽ có và bổ trợ rằng khi Item
lớp có một thuộc tính như Parent
:
class Item
{
public object Parent { get; private set; }
}
bạn có thể đặt setter riêng tư. Trong trường hợp này tất nhiên bạn không thể sử dụng một phương pháp mở rộng.
Nhưng có lẽ tôi đã sai và tôi chưa bao giờ thấy mẫu này trước đây vì nó không phổ biến? Bạn có biết liệu có bất kỳ mô hình như vậy?
Trong C#
một phương thức mở rộng sẽ hữu ích cho điều đó
public static T AddTo(this T item, IList<T> list)
{
list.Add(item);
return item;
}
Còn các ngôn ngữ khác thì sao? Tôi đoán trong hầu hết chúng, Item
lớp phải cung cấp một ICollectionItem
giao diện.
Cập nhật-1
Tôi đã suy nghĩ về nó nhiều hơn một chút và mẫu này sẽ thực sự hữu ích, ví dụ nếu bạn không muốn một mục được thêm vào nhiều bộ sưu tập.
ICollectable
giao diện kiểm tra :
interface ICollectable<T>
{
// Gets a value indicating whether the item can be in multiple collections.
bool CanBeInMultipleCollections { get; }
// Gets a list of item's owners.
List<ICollection<T>> Owners { get; }
// Adds the item to a collection.
ICollectable<T> AddTo(ICollection<T> collection);
// Removes the item from a collection.
ICollectable<T> RemoveFrom(ICollection<T> collection);
// Checks if the item is in a collection.
bool IsIn(ICollection<T> collection);
}
và triển khai mẫu:
class NodeList : List<NodeList>, ICollectable<NodeList>
{
#region ICollectable implementation.
List<ICollection<NodeList>> owners = new List<ICollection<NodeList>>();
public bool CanBeInMultipleCollections
{
get { return false; }
}
public ICollectable<NodeList> AddTo(ICollection<NodeList> collection)
{
if (IsIn(collection))
{
throw new InvalidOperationException("Item already added.");
}
if (!CanBeInMultipleCollections)
{
bool isInAnotherCollection = owners.Count > 0;
if (isInAnotherCollection)
{
throw new InvalidOperationException("Item is already in another collection.");
}
}
collection.Add(this);
owners.Add(collection);
return this;
}
public ICollectable<NodeList> RemoveFrom(ICollection<NodeList> collection)
{
owners.Remove(collection);
collection.Remove(this);
return this;
}
public List<ICollection<NodeList>> Owners
{
get { return owners; }
}
public bool IsIn(ICollection<NodeList> collection)
{
return collection.Contains(this);
}
#endregion
}
sử dụng:
var rootNodeList1 = new NodeList();
var rootNodeList2 = new NodeList();
var subNodeList4 = new NodeList().AddTo(rootNodeList1);
// Let's move it to the other root node:
subNodeList4.RemoveFrom(rootNodeList1).AddTo(rootNodeList2);
// Let's try to add it to the first root node again...
// and it will throw an exception because it can be in only one collection at the same time.
subNodeList4.AddTo(rootNodeList1);
add(item, collection)
, nhưng đó không phải là phong cách OO tốt.
item.AddTo(items)
giả sử bạn có ngôn ngữ không có phương thức mở rộng: tự nhiên hoặc không, để hỗ trợ addTo mọi loại sẽ cần phương thức này và cung cấp ngôn ngữ đó cho mọi loại bộ sưu tập hỗ trợ nối thêm. Đó giống như ví dụ tốt nhất về việc giới thiệu sự phụ thuộc giữa mọi thứ tôi từng nghe: P - Tôi nghĩ tiền đề sai ở đây là cố gắng mô hình hóa một số trừu tượng lập trình với cuộc sống 'thực'. Điều đó thường đi sai.