2014-01-10 8 views
2

Я пытаюсь внедрить шаблон фабрики, и у меня возникла проблема. Я стараюсь сделать мои классы простыми. В основном у меня есть базовый пакетный класс (PacketHeader) с некоторыми полями и методами. Также у меня так много производных классов пакетов, как: InfoPacket1011, UsagePacket1011, InfoPacket1014, UsagePacket1014, и все они наследуются от базового класса PacketHeader.Реализация заводского шаблона с различными типами возврата

Как вы можете видеть, каждый пакет имеет версию, и моя цель - обрабатывать эти пакеты на основе их версий. (!, Который сам по себе является производным классом) Таким образом, я должен иметь два производный класс, один для 1011 и один для 1014.

Базовый класс выглядит следующим образом:

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<???> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<???> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 

Моя проблема заключается в том, что для таких методов как BuildInfoPacket и BuildUsagePacket Мне нужно вернуть список этого типа. Таким образом, в производных классах я мог бы:

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override List<InfoPacket1011> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     // return List<InfoPacket1011> 
    } 
} 

public class PacketHandler1014 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override List<InfoPacket1014> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     // return List<InfoPacket1014> 
    } 
} 

Я не знаю, что использовать в классе PacketHandlerBase, чтобы иметь возможность переопределить его в производных классах. Наверное, мне нужны общие методы и интерфейс для этого, но не знаю, как с этим справиться.

[Изменить]: Я исправил первую часть своих вопросов о наследовании пакетов. Спасибо всем за ваши ответы, я прочитал их и расскажу, работают ли они.

[Ответить]: Спасибо всем за ваши быстрые ответы. Я исправил проблему, передав List и выбрав его в методе и в вызывающем. Ну, мой код был намного сложнее, чем я здесь, и я только что закончил его модификацию. Я изменил шаблон на абстрактную фабрику, чтобы исправить некоторые другие проблемы.

Любая помощь была бы принята с благодарностью. Заранее спасибо

+0

Что относительно списка ? – felipekm

ответ

1

Вы реализуете на самом деле в Abstract Factory шаблон, где PackerHandlerBase является Abstract Factory и производит/строит абстрактный продукт в вашем случае является InfoPacket и UsagePacket. Бетонный завод является PacketHandler1011 или PacketHandler1014. И Бетонный продукт is InfoPacket1011 или InfoPacket1014 и так далее.

Так оно и должно быть:

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<InfoPacket> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<UsagePacker> BuildUsagePacket(string someInput); 
    //... 
} 

public class InfoPacket1014 : InfoPacket 
{ 
    ///... 
} 

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override List<InfoPacket> BuildInfoPacket(string someInput); 
    { 
     // code implementation 
     return new List<InfoPacket> { new InfoPacket1011(), ... }; 
    } 
} 
0

Вот пример, чтобы использовать его общий способ: Используйте объекты в типе ограничения, как:

where T : InfoPacketBase и в производном классе метод: List<InfoPacket1011>;

abstract class A 
{ 
    public abstract List<T> BuildInfoPacket<T>(string someInput) where T : new(); 
} 

class B : A 
{ 
    public override List<T> BuildInfoPacket<T>(string someInput) 
    { 
     // code implementation 
     return new List<T> { new T() }; 
    } 

    public void Test() 
    { 
     BuildInfoPacket<object>("test"); 
    } 
} 
+0

Это не скомпилируется. Вы имели в виду сделать этот метод общим? – svick

+0

Да, точно. Моя ошибка, я исправил. – speti43

3

весь ваш метод базового класса должен возвращать InfoPacketBase, а также создание базового класса для использования пакетов, например UsagePacketBase вам нужно взглянуть на polymorphism

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<PackeHeader> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<PackeHeader> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 
+0

Спасибо Julie, , что было моим предпочтительным способом использования наследования! Но я изменяю чужой код, и я не могу (это невозможно) изменить наследование пакета. У меня есть PackeHeader и все остальные пакеты, наследуемые от этого базового класса. – Kian

+0

, так что вы можете использовать PacketHeader вместо InfoPacketBase или UsagePacketBase посмотреть мой ответ, он обновлен сейчас –

+0

Еще раз спасибо Julie, Я действительно пытался это сделать раньше, но у меня были проблемы, по-видимому, моя проблема была связана с неправильным литьем. Я решил проблему, используя комбинацию вашего ответа и ответа Конарда. – Kian

0

Как насчет:

public abstract class PacketHandlerBase<TInfoPacket, TUsagePacket> : Engine 
    where TInfoPacket : IInfoPacket 
    where TUsagePacket : IUsagePacket 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract List<TInfoPacket> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract List<TUsagePacket > BuildUsagePacket(string someInput); 
} 

Вы убедитесь, что ваши классы пакетов информации реализуют интерфейс IInfoPacket. Например:

public InfoPacket1101 : PacketHeader, IInfoPacket 
{ 
    ... 
} 

Аналогичным образом все классы пакетов использования реализуют IUsagePacket. Тогда вы можете написать данную версию обработчика пакетов так:

public class PacketHandler1011 : PackerHandlerBase<InfoPacket1101, UsagePacket1101> 
{ 
    ... 
} 

Я думаю, что это является предпочтительным решением, так как это означает, что вы можете иметь более надежные гарантии относительно возвращенных объектов.При использовании только одного базового класса, как и в принятом в настоящее время ответе, вы не можете вызывать какие-либо «информационные пакеты» -специфические методы для объектов, возвращаемых BuildInfoPacket без кастинга. Аналогично пакетам использования. В этом решении интерфейс IInfoPacket может иметь методы, которые затем можно вызывать без кастинга.

+1

Я имею в виду, что вы бы просто определили один тип параметра TPacket, а затем объявление метода было бы «публичным абстрактным списком BuildInfoPacket (string someInput);" но C# не поддерживает такого рода смешивание типов. –

+0

Thanks Martin, Моя проблема в том, что все пакеты наследуются от базового класса PacketHeader, и нет никакого способа изменить это наследование. – Kian

+0

Это не проблема: вместо InfoPacketBase и т. Д. Используют интерфейсы. Я обновляю свой ответ, чтобы отразить это. –

0

Не использовать дженерики, если вы не понимаете их и полностью осведомлены о своих недостатков. В этом случае вы можете просто вернуть IEnumerable<PacketHeader> и решить проблему полиморфизма.

public abstract class PacketHandlerBase : Engine 
{ 
    public abstract bool SendInfoPacket(int someInt, string someInput); 
    public abstract IEnumerable<PacketHeader> BuildInfoPacket(string someInput); 

    public abstract bool SendUsagePacket(int someInt, string someInput); 
    public abstract IEnumerable<PacketHeader> BuildUsagePacket(string someInput); 
    //... 
    //... 
    //... 
} 

public class PacketHandler1011 : PackerHandlerBase 
{ 
    //... 
    public override bool SendInfoPacket(int someInt, string someInput); 
    { 
     // code implementation 
     // return true or false 
    } 

    public override IEnumerable<PacketHeader> BuildInfoPacket(string someInput); 
    { 
     yield return new InfoPacket1011(..) 
     // code implementation 
     // return List<InfoPacket1011> 
    } 
} 
Смежные вопросы