Tôi đang theo dõi câu hỏi này , nhưng tôi đang chuyển trọng tâm của mình từ mã sang nguyên tắc.
Từ sự hiểu biết của tôi về nguyên tắc thay thế Liskov (LSP), bất kể phương pháp này trong lớp cơ sở của tôi, họ phải được thực hiện trong lớp con của tôi, và theo này trang, nếu bạn ghi đè một phương pháp trong các lớp cơ sở và nó không làm gì hoặc ném một ngoại lệ, bạn đang vi phạm nguyên tắc.
Bây giờ, vấn đề của tôi có thể được tóm tắt như thế này: tôi có một bản tóm tắt Weapon class, và hai lớp, Swordvà Reloadable. Nếu Reloadablechứa một cụ thể method, được gọi Reload(), tôi sẽ phải downcast để truy cập vào đó method, và, lý tưởng nhất, bạn muốn tránh điều đó.
Sau đó tôi nghĩ đến việc sử dụng Strategy Pattern. Bằng cách này, mỗi vũ khí chỉ nhận thức được các hành động mà nó có khả năng thực hiện, vì vậy, ví dụ, Reloadablevũ khí, rõ ràng có thể tải lại, nhưng Swordkhông thể, và thậm chí không nhận ra Reload class/method. Như tôi đã nói trong bài viết Stack Overflow của mình, tôi không phải xem thường và tôi có thể duy trì một List<Weapon>bộ sưu tập.
Trên một diễn đàn khác , câu trả lời đầu tiên đề nghị cho phép Swordnhận thức được Reload, chỉ cần đừng làm gì cả. Câu trả lời tương tự này được đưa ra trên trang Stack Overflow mà tôi đã liên kết ở trên.
Tôi không hiểu tại sao. Tại sao vi phạm nguyên tắc và cho phép Sword nhận thức Reloadvà để trống? Như tôi đã nói trong bài viết Stack Overflow của tôi, SP, đã giải quyết khá nhiều vấn đề của tôi.
Tại sao nó không phải là một giải pháp khả thi?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
Giao diện tấn công và thực hiện:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()trống hoặc standardActionskhông chứa hành động tải lại chỉ là một cơ chế khác. Không có sự khác biệt cơ bản. Bạn có thể làm cả hai. => Giải pháp của bạn là khả thi (đó là câu hỏi của bạn) .; Kiếm không cần biết về tải lại nếu Weapon chứa triển khai mặc định trống.
class Weapon { bool supportsReload(); void reload(); }. Khách hàng sẽ kiểm tra nếu được hỗ trợ trước khi tải lại.reloadđược xác định theo hợp đồng để ném iff!supportsReload(). Điều đó tuân thủ các lớp học LSP iff tuân thủ giao thức tôi vừa phác thảo.