Làm thế nào tôi có thể xử lý hàng tồn kho theo cách hướng đối tượng?


7

Tôi đang cố gắng nghĩ ra cách tốt nhất để xử lý hàng tồn kho của người chơi theo cách tiếp cận hướng đối tượng.

Ví dụ, kiếm và rìu là hai lớp khác nhau, cả hai đều thừa hưởng từ vũ khí. Vũ khí và thuốc cũng là những lớp khác nhau cả hai kế thừa từ vật phẩm.

Lý tưởng nhất là hàng tồn kho sẽ được triển khai như một thùng chứa các mặt hàng, nhưng điều đó không thể được thực hiện vì nhiều lý do. Vì vậy, nó phải là một thùng chứa các con trỏ vật phẩm (thông minh). Vì tôi không muốn đọc mã của mình bằng các lệnh gọi mới và xóa, tôi sẽ bọc nó trong một lớp ItemWrapper có tin tức / xóa trên ctor / dtor.

Vì vậy, mã sẽ trông giống như thế này

class Sword;
class ItemWrapper;

//Prepare the long sword.
const Sword longSword(...params...);

//Declare the inv
vector<ItemWrapper> inv;

 //Add it to inventory
inv.push_back(longSword);  //compiles if ItemWraper(const Sword&) is defined.

Cách tiếp cận này là cách tốt nhất tôi có thể đưa ra về mặt rõ ràng của mã và dễ viết. Vấn đề là ItemWrapper sẽ cần một hàm tạo cho mỗi lớp lá kế thừa từ Item (rất nhiều).

Đây là nỗ lực đầu tiên của tôi ở đây, vì vậy tôi muốn biết: tôi có đi đúng hướng không? hoặc nếu có một cách tốt hơn để làm điều đó (có lẽ là một cách tránh rất nhiều nhà xây dựng)?


Tôi thực sự quan tâm đến cách thức này được thực hiện tốt nhất.
Tili

Câu trả lời:


9

Có một cái gì đó bạn đang làm ngay bây giờ mà bạn có thể thấy rằng bạn hối hận về sau, mặc dù nó có vẻ như là một điều hợp lý để làm.

Bạn có thể thấy rằng làm cho mỗi loại mặt hàng trở nên khó quản lý khi bạn có hơn mười hai trong số chúng.

Hệ thống quản lý hàng tồn kho của riêng tôi không có các loại khác nhau cho các mặt hàng. Thay vào đó, tôi sử dụng lớp "Mô tả", có một tập các thuộc tính (cặp Tên-Giá trị, được lưu trữ trong một thùng chứa kết hợp [trong C ++, bạn có thể sẽ sử dụng std :: map])

Trình lấy thuộc tính là một hàm mẫu để biến thuộc tính từ bản đồ thành loại thích hợp.

Cách tôi phân biệt giữa các loại vật phẩm là có thuộc tính ItemType, thường là một loại enum với các mục như WEAPON, ARMOR, v.v. Các thuộc tính khác chứa phạm vi thiệt hại, tham chiếu đến hình ảnh để sử dụng để hiển thị nó, mô tả tên, v.v.

Bây giờ, những mô tả này không dành cho các trường hợp mục. Họ mô tả các loại mặt hàng nói chung. Các thể hiện của vật phẩm chứa một số loại tham chiếu đến bộ mô tả cũng như một bản đồ các thuộc tính tương tự cho các giá trị cần thiết cho một thể hiện vật phẩm (ví dụ như độ bền riêng lẻ). Theo cách này, người ta tránh lặp đi lặp lại cùng một thông tin. Rốt cuộc, một thanh kiếm cũng giống như một thanh kiếm khác, nó có thể gần như bị hao mòn hơn.

Để tránh các cuộc gọi của nhà xây dựng, tôi khuyên bạn nên sử dụng một phương thức xuất xưởng.


4
Tôi nghĩ rằng bạn có thể là một chút xa hơn tôi sẽ. Tôi nghĩ không có lý do gì để tạo ra một lớp VorpalBladeOfPower và một lớp PunyIronHandaxe; nhưng có các loại riêng biệt cho vũ khí, áo giáp, vv có thể giúp bạn tiết kiệm nỗi đau. Hãy để trình biên dịch ngăn người chơi sử dụng hai bình thuốc và mũ bảo hiểm.
dhasenan

Tôi hiểu quan điểm của bạn về việc hợp nhất các mục thành một lớp. Tôi thực sự không hiểu tại sao lưu trữ các tài sản bên trong một thùng chứa kết hợp. Nếu tôi hiểu chính xác (và nói nếu tôi hiểu sai), thay vì một float weightbiến trong Itemlớp bạn giữ số trong một thùng chứa (có lẽ liên quan đến nhãn "trọng lượng"). Có vẻ như bạn thực hiện một cú đánh hiệu suất nhỏ (đọc từ container) và viết thêm mã, để đổi lấy một chút bộ nhớ.
Malabarba

Tất nhiên, tôi cho rằng kết cấu và âm thanh đã được quản lý bộ nhớ (vì chúng phải luôn như vậy). Trong trường hợp đó, tôi tin rằng lợi thế của việc quản lý bộ nhớ một vài floats, enums và ints trên mỗi phiên bản Item (ngay cả khi có hàng trăm phiên bản Item) sẽ không đáng kể.
Malabarba

Nó sẽ là một hit hiệu suất nếu bạn có hàng ngàn thuộc tính trong mỗi mô tả. Nói chung, có ít hơn 20 tài sản trong hầu hết các tài sản này.
PlayDeezGames

Xin lỗi, "hiệu suất thành công" không phải là trọng tâm, tôi biết nó rất nhỏ hoặc thậm chí không có. Quan điểm của tôi là có vẻ như bạn đang viết nhiều mã hơn và tiết kiệm 1 hoặc 2 MB bộ nhớ (giả sử hàng trăm mục).
Malabarba

7

Ví dụ, kiếm và rìu là hai lớp khác nhau, cả hai đều thừa hưởng từ vũ khí. Vũ khí và thuốc cũng là những lớp khác nhau cả hai kế thừa từ vật phẩm.

Tôi sẽ không làm mọi thứ theo cách này; một thanh kiếm và rìu khác nhau chủ yếu trong dữ liệu của họ, không phải là hành vi cơ bản của họ như vũ khí. Tương tự như vậy với các mặt hàng. Tôi sẽ tránh việc lạm dụng quyền thừa kế này, bắt đầu bằng cách giới hạn bản thân mình WeaponItem(bạn thậm chí có thể xếp chúng vào một lớp duy nhất, nhưng đó là một cuộc thảo luận khác). Nếu không có gì khác, điều này sẽ làm giảm bớt vụ nổ của nhà xây dựng mà bạn đang thấy ItemWrapper.

Vì vậy, nó phải là một thùng chứa các con trỏ vật phẩm (thông minh). Vì tôi không muốn đọc mã của mình bằng các lệnh gọi mới và xóa, tôi sẽ bọc nó trong một lớp ItemWrapper có tin tức / xóa trên ctor / dtor.

Hãy xem xét Boost con trỏ thông minh thay vì tự lăn. Chúng khá tách biệt với phần còn lại của Boost (vì vậy bạn không có quá nhiều sự phụ thuộc để tham gia nếu vì lý do nào đó, bạn không muốn tận dụng phần còn lại của công cụ gọn gàng của Boost) và nhiều chúng đã được chấp nhận là một phần của thư viện tiêu chuẩn mới trong C ++ 11, vì vậy bạn không nên gặp vấn đề nâng cấp.

Đây là nỗ lực đầu tiên của tôi ở đây, vì vậy tôi muốn biết: tôi có đi đúng hướng không? hoặc nếu có một cách tốt hơn để làm điều đó (có lẽ là một cách tránh rất nhiều nhà xây dựng)?

Như trên, tôi sẽ cố gắng tránh kế thừa cho việc này và xem xét sử dụng các giải pháp của bên thứ ba đã được thiết lập thay vì tự mình thực hiện. Những bước đó một mình sẽ loại bỏ phần lớn sự phức tạp bảo trì mà bạn đang khám phá (hoặc sẽ sớm khám phá).

Điều đó nói rằng, một cách tiếp cận khác là xem xét nó theo cách này: ItemWrapperlà một hỗ trợ ban nhạc cho một vấn đề chi tiết thực hiện. Bản thân nó không đại diện cho một "đối tượng" thực sự theo bất kỳ ý nghĩa điển hình nào. Vì vậy, hãy suy nghĩ về những gì có thể là một sự tương tự tốt hơn cũng giải quyết vấn đề của bạn là có một nơi để đặt tự động newdeletecác cuộc gọi.

Hầu hết hàng tồn kho cho phép (một số) vật phẩm xếp chồng lên nhau, phải không?

"Khả năng xếp chồng" của một vật phẩm là một thuộc tính của vật phẩm đó, nhưng bản thân vật phẩm đó không chịu trách nhiệm duy trì ngăn xếp. Nếu bạn có một lớp đại diện cho một ItemStackphương thức để truy vấn kích thước của ngăn xếp, tách ngăn xếp, et cetera thì bạn có thể đặt quyền quản lý vòng đời của con trỏ vật phẩm (mà tôi cần lưu ý, có thể trở nên phức tạp hơn một chút với các ngăn xếp , do đó cung cấp một đối số khác để sử dụng một cái gì đó như Boost) trong lớp stack cùng với việc thực hiện phần còn lại của hành vi của nó. Các mục không thể xếp chồng được thể hiện bằng một ngăn xếp luôn chứa một mục duy nhất và bản thân kho lưu trữ của bạn vẫn xử lý các trường hợp đồng nhất của ItemStack.


+1 Kết hợp WeaponItemsẽ là chiếc đinh cuối cùng trong quan tài cho ItemWrapper. Weaponcó thể mở rộng Itemhoặc cả hai có thể mở rộng một lớp cơ sở chung. Sau đó, bạn có thể có một cái gì đó nhưvector<shared_ptr<Item> > inv;
Gyan aka Gary Buyn

Sử dụng một ItemStack có vẻ như là một ý tưởng tốt.
Malabarba
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.