2011-01-04 46 views
35

Tôi là người mới và cố gắng hiểu khái niệm về mẫu kế thừa và thiết kế.Truyền lớp bắt nguồn làm tham số cho một phương thức khi kiểu tham số là lớp cơ sở

Tôi đã xem mẫu này http://en.wikipedia.org/wiki/Strategy_pattern khi tôi xem qua một số blog.

Tôi thấy nó thú vị và muốn tìm hiểu thêm. Vì vậy, tôi đã phát triển chương trình sau.

static void Main(string[] args) 
{ 
    Context context; 

    // Three contexts following different strategies 
    context = new Context(new ConcreteStrategyAdd()); 
    int resultA = context.executeStrategy(3, 4); 

    context = new Context(new ConcreteStrategySubtract()); 
    int resultB = context.executeStrategy(3, 4); 

    context = new Context(new ConcreteStrategyMultiply()); 
    int resultC = context.executeStrategy(3, 4); 

    Console.Read(); 
}  

abstract class Strategy 
{ 
    public abstract int execute(int a, int b); 

    public void Test() 
    { 
     Console.Write("tttt"); 
    } 
} 

class ConcreteStrategyAdd : Strategy 
{ 
    public override int execute(int a, int b) 
    { 
     Console.WriteLine("Called ConcreteStrategyAdd's execute()"); 
     return a + b; // Do an addition with a and b 
    } 
} 

class ConcreteStrategySubtract : Strategy 
{ 

    public override int execute(int a, int b) 
    { 
     Console.WriteLine("Called ConcreteStrategySubtract's execute()"); 
     return a - b; // Do a subtraction with a and b 
    } 
} 

class ConcreteStrategyMultiply : Strategy 
{ 
    public override int execute(int a, int b) 
    { 
     Console.WriteLine("Called ConcreteStrategyMultiply's execute()"); 
     return a * b; // Do a multiplication with a and b 
    } 
} 

class Context 
{ 
    private Strategy strategy; 

    // Constructor 
    public Context(Strategy strategy) 
    { 
     this.strategy = strategy; 
    } 

    public int executeStrategy(int a, int b) 
    { 
     return strategy.execute(a, b); 
    } 
} 

Chương trình biên dịch tốt và đang hoạt động. Nhưng câu hỏi của tôi là làm thế nào là nó có thể vượt qua lớp dẫn xuất như một tham số khi các nhà xây dựng Context là mong đợi lớp cơ sở như một tham số? Việc đúc diễn ra có ngầm không? Tại sao trình biên dịch không lỗi?

context = new Context(new ConcreteStrategyAdd()); 

public Context(Strategy strategy) 
{ 
    this.strategy = strategy; 
} 
+7

+1 cho một câu hỏi mới bắt đầu tốt! –

+1

Đối với một newbie, bạn đang hỏi tất cả các câu hỏi đúng :) +1 – MattDavey

Trả lời

25

Đặt thực sự đơn giản:

Một lớp Derived (hoặc lớp con) một thể hiện của lớp cơ sở của nó.

Vì vậy, khi bạn vượt qua một thể hiện của ConcreteStrategyAdd vào constructor, bạn là chủ yếu thông qua một đối tượng Strategy trong

. Không có đúc liên quan. Phân cấp kiểu cho phép loại lập trình này. Nó cho phép các lập trình viên sử dụng polymorphism trong mã của họ.

+0

Tôi muốn vượt qua một lớp Type như một tham số (không phải là cá thể của nó) và vẫn giới hạn giá trị của một lớp cơ sở phân cấp lớp. để đạt được biên dịch thời gian kiểm tra về điều này? Ví dụ, Java cho phép Class như là một paremeter (như lớp Class của nó là generic), thật không may .net Kiểu không phải là generic: -/ Oh tôi phải đề cập đến, tôi đang cố gắng làm điều này cho một nhà xây dựng - vì vậy generics không cho phép –

2

Lớp dẫn xuất là lớp cơ sở. (Đó là toàn bộ khái niệm thừa kế: thừa kế định nghĩa một 'là một' mối quan hệ).

Ngoài ra, hãy xem Liskov substitution principle. :)

+1

liên kết đó khiến tôi khá bối rối, thay vì giúp đỡ. – BerggreenDK

+0

LSP chắc chắn là thích hợp cho chủ đề này nhưng có lẽ hơi quá nâng cao cho một câu hỏi mới bắt đầu :) – MattDavey

2

dễ hiểu hơn nếu bạn sử dụng ví dụ đơn giản hơn so với mẫu chiến lược.

giả sử bạn có một lớp được gọi là "Trái cây" và một lớp được gọi là "Apple" có nguồn gốc từ trái cây. bất kỳ phương pháp nào được viết để làm việc với Trái cây nói chung đều có thể hoạt động tốt với Apple hoặc bất kỳ loại trái cây cụ thể nào khác

24

Không cần đúc, vì ConcreteStrategyAdd một Chiến lược - nó đáp ứng tất cả các yêu cầu của một chiến lược. Đây là nguyên tắc đa hình.

Có lẽ một ví dụ đơn giản hơn là cần thiết:

abstract class Fruit { } 

class Apple : Fruit { } 
class Orange : Fruit { } 
class Melon : Fruit { } 

class FruitBasket 
{ 
    void Add(Fruit item) { ... } 
} 

FruitBasket basket = new FruitBasket(); 
basket.Add(new Apple()); // Apple IS A fruit 
basket.Add(new Orange()); // Orange IS A fruit 
basket.Add(new Melon()); // Melon IS A fruit 

class Potato : Vegetable { } 

basket.Add(new Potato()); // ERROR! Potato IS NOT A fruit. 
+2

Tôi thích "ví dụ thực tế". Tốt nhất.Ô tô và hoa quả là những ví dụ tuyệt vời. – BerggreenDK

+0

Đó là một ví dụ hay, và có thể rõ ràng hơn với một số ví dụ B: A và xe hơi thông thường. –

Các vấn đề liên quan