Mô hình này là gì, và tôi nên làm điều đó?


9

Tôi đang tạo một trò chơi trong as3 bằng cách sử dụng flash phát triển và flash cs5. Mọi thứ đều hướng đối tượng. Tôi đã tự hỏi, liệu tôi có nên có một lớp "gateway" có tham chiếu thuộc tính cho tất cả các tức thời của các lớp khác không và tôi chỉ chuyển lớp cổng này cho các đối tượng mới, để chúng có quyền truy cập vào mọi lớp. Thích như vậy:

 var block:Block = new Block(gateway);

 //In the block class:
 this.gateway.player.setHealth(100);
 //Or:
 this.gateway.input.lock();

Đây có giống như một mẫu singleton hay cái gì đó không? Tôi có nên làm điều này?

Câu trả lời:


13

Đây được gọi là mẫu thiết kế đối tượng bối cảnh và nó tốt hơn mẫu singleton.

  • Kiểm tra hỗ trợ các đối tượng bối cảnh, bởi vì bạn có thể chuyển các bối cảnh giả cho các chức năng bạn muốn kiểm tra. Singletons cản trở nó, bởi vì để chế giễu những người độc thân, bạn cần làm cho họ không phải là những người độc thân.
  • Các đối tượng bối cảnh làm cho "trạng thái toàn cầu" của bạn rõ ràng, và do đó dễ dàng lý luận hơn. Nếu một hàm không lấy một đối tượng ngữ cảnh, bạn biết nó không sử dụng bất kỳ trạng thái bối cảnh toàn cầu nào. Bạn không có sự đảm bảo như vậy với singletons hoặc các biến toàn cục.
  • Các đối tượng bối cảnh sẽ chậm hơn một chút nếu bạn không sử dụng chúng, bởi vì bạn thêm một tham số khác cho tất cả các lệnh gọi hàm của bạn. Chúng có thể nhanh hơn toàn cầu nếu bạn sử dụng chúng và gần như luôn luôn nhanh hơn so với singletons.
  • Các đối tượng bối cảnh dễ thực hiện hơn; thông thường họ sống trên đống hoặc chồng một cách bình thường. Singletons có các vấn đề phức tạp liên quan đến luồng trong nhiều ngôn ngữ.

Vì vậy, đây không phải là một người độc thân, nó tốt hơn so với một người độc thân.

Tuy nhiên, bạn vẫn đang vượt qua một trạng thái tào lao - thực tế là bạn giữ tất cả trong một biến cục bộ duy nhất làm cho nó rõ ràng hơn, nhưng vẫn tạo ra sự lo ngại lớn . Hãy ghi nhớ quy tắc một trách nhiệm . Điều này có ý nghĩa đối với việc có một bối cảnh sở hữu trình phát và cấp độ hiện tại - chúng có liên quan - nhưng tại sao cùng một bối cảnh lại sở hữu đầu vào bàn phím của bạn?

Xem xét các cấp độ bối cảnh khác nhau, ví dụ:

  • GameplayContext - sở hữu người chơi, kẻ thù, hình học cấp độ, v.v.
  • InputContext - sở hữu bàn phím và tay cầm chuột, các sự kiện đầu vào, v.v.
  • GraphicsContext - sở hữu kết cấu, tay cầm cửa sổ, v.v.
  • GlobalContext - sở hữu GameplayContext, GraphicsContext và InputContext. Đây là nơi bạn muốn áp dụng mẫu định vị dịch vụ , để có thể trao đổi một số bối cảnh cho các bối cảnh khác khi cần. Và có lẽ, để lặp lại và thử nghiệm nhanh, đây phải là một biến toàn cầu thực sự - chỉ cần nhận ra rằng bất cứ khi nào bạn sử dụng nó, bạn đang xây dựng nợ công nghệ .

Các bối cảnh này vẫn khiến chúng ta lo ngại phần nào - có thể một số người xử lý sự kiện lấy GameplayContext và thực sự chỉ cần người chơi - nhưng các trách nhiệm được đặt ra rõ ràng. Bạn biết rằng một cái gì đó có GameplayContext sẽ không tải kết cấu; một cái gì đó lấy InputContext không thể giết người chơi.


+1 Câu trả lời hay. Mặc dù vậy, một số lo ngại về tốc độ hoặc luồng không thực sự áp dụng trong ngữ cảnh này (ActionScript3 không hỗ trợ luồng và rất nhiều cơ chế cải thiện tốc độ hoạt động trong C ++ không áp dụng khi sử dụng AS3).
bummzack

Tôi không biết nhiều về AS3VM, nhưng trong hầu hết các ngôn ngữ động, chi phí truyền / nhận / sử dụng một địa phương vẫn nhanh hơn là (mảng tra cứu) so với chi phí của nhìn lên một (tra cứu băm) toàn cầu, và nhiều nhanh hơn gọi một hàm (craploads của công cụ) để có được nó. Vì vậy, tôi nghĩ rằng lời khuyên vẫn được áp dụng.

0

Điều này không giống như mô hình Singleton. Theo cách tôi hiểu, bạn đang truyền một đối tượng có tham chiếu đến các đối tượng trò chơi quan trọng cho tất cả các phiên bản của bạn.

Nếu đây là mẫu Singleton, bạn sẽ có:

AudioManager.getInstance().playSound(XY);

Trong trường hợp của bạn, bạn có thể có:

this.gateway.getAudioManager().playSound(XY);

Về cơ bản trông giống nhau, nhưng thực sự không phải vậy. Nếu bạn muốn thay thế AudioManagerbằng một kiểu mới (lớp mở rộng) ExtendedAudioManager, bạn sẽ nhấn một bức tường bằng cách sử dụng mẫu Singleton. Cách tiếp cận cổng của bạn sẽ xử lý đó chỉ là tốt mặc dù.

Hạn chế của phương pháp của bạn là bạn sẽ phải đi gatewaykhắp nơi. Mẫu định vị dịch vụ (được đề xuất bởi Joe Wreschnig trong chuỗi này ), trông giống như một sự thay thế tốt cho "mẫu cổng" của bạn.

Đôi khi, tốt hơn hết là chỉ chạy với phương pháp đơn giản và đơn giản thay vì thiết kế quá nhiều thứ. Đặc biệt là khi đó là một dự án nhỏ hoặc một nguyên mẫu. Có lẽ bạn có thể làm cho gatewaymột số loại biến toàn cục .. ví dụ. Game.gatewayvà chạy với nó.


-2

Hầu hết các giải pháp cho vấn đề này, bao gồm cả mẫu Singleton, liên quan đến việc sử dụng các biến tĩnh. Nếu bạn chỉ có một người chơi, bạn có thể có Người chơi là một lớp đơn, điều đó có nghĩa là bạn có thể truy cập vào thể hiện Người chơi thông qua một cái gì đó như Player.cienPlayer. Tuy nhiên, nhiều người nổi giận chống lại Singletons. Bạn cũng có thể có một ResourceManager hoặc lớp tương tự có chứa các tham chiếu tĩnh đến các biến toàn cục hữu ích hoặc khá phổ biến khác nhau. Trong mã của bạn, bạn cũng có thể tạo các biến "Gateway" có thể truy cập tĩnh thay vì thổi phồng mã của mình bằng cách chuyển mã đi khắp nơi.


Câu hỏi đã thay đổi đáng kể kể từ khi tôi đưa ra câu trả lời này, đủ để nó có vẻ không đáng để chỉnh sửa nó.
Gregory Avery-Weir

2
Ngoài tiêu đề, không có gì thay đổi trong câu hỏi.
bummzack

1
Gì? Không có gì thay đổi ngoài tiêu đề. -1
Tấn

Tôi nghĩ rằng tôi đã nghĩ về tiêu đề ở đây; Tôi nhớ tiêu đề ban đầu là một cái gì đó như "Tôi nên làm điều này như thế nào?" Hoàn toàn có thể là tôi đã đọc sai tiêu đề / câu hỏi ban đầu khi tôi trả lời.
Gregory Avery-Weir
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.