Нужен совет как спроектировать это. Композиция или наследство? - PullRequest
0 голосов
/ 24 сентября 2011

Я пытаюсь разработать клиент-серверное решение.В настоящее время он содержит три проекта.Клиент, сервер и библиотека, которые каждый использует (потому что они оба требуют много одного и того же материала).

Например, и клиент, и сервер (в данном случае) читают входящие данные вточно так же.Из-за этого и клиент, и сервер имеют свой собственный объект MessageReader.MessageReader сначала прочитает первые 4 байта данных входящего потока, чтобы определить длину данных, а затем прочитает остальные.Все это выполняется асинхронно.Когда все данные прочитаны, класс вызывает свое собственное событие MessageRead или, если при чтении было IOException, возникает собственное событие ConnectionLost.

Так что все это прекрасно работает.В чем проблема?Ну, клиент и сервер немного отличаются.Например, хотя они могут считывать данные одинаково, они не записывают данные одинаково.Сервер имеет Dictionary клиентов и имеет метод Broadcast для записи всем клиентам.Клиент имеет только один TcpClient и может только Write на сервер.В настоящее время все это поведение присутствует в каждой соответствующей WinForm, и я хочу переместить его в класс Client и Server, но у меня возникли некоторые проблемы.

Например, помните ранее, когда я говорил оMessageReader и как он может вызвать и событие MessageRead, и событие ConnectionLost?Что ж, теперь есть небольшая проблема, потому что при разработке класса Client мне нужно захватить эти два события и повторно вызвать их, потому что клиентская форма не должна иметь доступа к классу MessageReader.Это немного уродливо и выглядит так:

class Client
{
    private MessageReader messageReader = new MessageReader();

    public delegate void MessageReceivedHandler(string message);
    public delegate void ConnectionLostHandler(string message);

    public event ConnectionLostHandler ConnectionLost;
    public event MessageReceivedHandler MessageReceived;

    public Client()
    {
        messageReader.ConnectionLost += messageReader_ConnectionLost;
        messageReader.MessageReceived += messageReader_MessageReceived;
    }

    private void messageReader_MessageReceived(string message)
    {
        if (ConnectionLost != null)
        {
            ConnectionLost(message);
        }
    }

    private void messageReader_ConnectionLost(string message)
    {
        if (MessageReceived != null)
        {
            MessageReceived(message);
        }
    }
}

Этот код уродлив, потому что в основном это дублирующий код.Когда MessageReader поднимает обработчик MessageReceieved, Client должен перехватить его и в основном повторно вызвать свою собственную версию (дублированный код), потому что клиентская форма не должна иметь доступа к читателю сообщений.

Не очень хороший способ решить это.Я полагаю, что и Client, и Server могут быть получены из абстрактного DataReader, но я не думаю, что клиент является считывателем данных , как и сервер.Я чувствую, что композиция имеет более логичный смысл, но я не могу придумать способ сделать это без большого количества дублирования кода и запутанных обработчиков событий.

Ой, этот вопрос становится немного длинным ... Я надеюсьЯ никого не пугаю длиной.Это, вероятно, простой вопрос, но я не совсем уверен, что делать.

Спасибо за чтение.

Ответы [ 2 ]

2 голосов
/ 24 сентября 2011

Состав.

Я даже не читал ваш код или текст. Я считаю, что среднестатистический разработчик (почти) никогда не нуждается в наследовании, но ему нравится использовать его совсем немного.

Наследование хрупкое. Наследование трудно получить правильно. С SOLID все сложнее контролировать.

Композиция проста для понимания, легко изменяется и проста для DI, макета и тестирования.

SOLID

0 голосов
/ 29 сентября 2011

Я закончил тем, что использовал наследование для этого, хотя отношения не были крепкими.Дублирование кода, от которого он избавился, того стоило.Был в состоянии поместить все события, которые оба класса совместно использовали, в базовый класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...