Слабая связь статического материала - PullRequest
3 голосов
/ 14 июля 2010

У меня есть класс ClassA, который использует клиент, которого я написал для отправки текстовых сообщений, TextClient, чтобы отправить некоторые текстовые сообщения через вызов статического метода

TextClient.Send(string text, string destination)
// where destination is a phone number

Однако ятакже есть класс почтового клиента MailClient, который отправляет электронные письма с такой же подписью:

MailClient.Send(string text, string destination)
// where destination is an email address

Я хотел бы "ввести", какой из этих клиентов следует использовать - возможно ли это?

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

Ответы [ 5 ]

7 голосов
/ 14 июля 2010

В основном, избавьтесь от статических методов.Создайте интерфейс (IMessageClient), а затем две реализации (TextClient и MailClient) с методами экземпляра, реализующими интерфейс.Затем вы можете легко вставить соответствующий IMessageClient в остальную часть приложения.

Вы, конечно, можете использовать делегатов, чтобы избежать создания интерфейса здесь - но я бы определенно переключился на использование интерфейсоввместо этого:

  • Используемые имена (имя интерфейса, имя метода и имена параметров) передают информацию при их использовании
  • Это позволяет использовать несколько методов в одном интерфейсе
  • Предотвращает случайное использование методов, которые имеют одинаковые типы аргументов, но имеют совершенно не связанное значение
4 голосов
/ 14 июля 2010

Конечно, пусть ваши клиенты реализуют некоторый интерфейс отправки.

public interface IMessageClient
{
    public void Send(string text, string destination);
}

public class TextClient : IMessageClient
{
    public void Send(string text, string destination)
    {
        // send text message
    }
}

public class MailClient : IMessageClient
{
    public void Send(string text, string destination)
    {
        // send email
    }
}

public class ClassA
{
    private IMessageClient client;

    public ClassA(IMessageClient client)
    {
        this.client = client;
    }
}

То же, что и ответ Джона Скита, но он победил меня, не набрав код.

2 голосов
/ 14 июля 2010

Как правило, лучше избегать статических классов при разработке таких служб, потому что это усложняет отделение от другого кода.

Если у вас есть контроль над дизайном и реализацией классов TextClient и MailClient, я бы посоветовал сделать их singleton экземплярами классов, а не статическими классами. Затем вы можете реализовать общий интерфейс IMessageSender (см. Ниже) в обоих случаях и передать его в качестве экземпляра объекту, который должен выполнить вызов.

public interface IMessageSender
{
    void Send( string message, string destination );
}

public class TextClient : IMessageSender { ... }
public class MailClient : IMessageSender { ... }

Если у вас нет контроля над реализацией этих классов (или вы не можете изменить их в данный момент), вы можете передать делегат в объект, который должен сделать вызов:

class SomeConsumer
{
    private Action<string,string> m_SendDelegate;
    public SomeConsumer( Action<string,string> sendDelegate ) 
    { 
        m_SendDelegate = sendDelegate;
    } 

    public DoSomething()
    {
        // uses the supplied delegate to send the message
        m_SendDelegate( "Text to be sent", "destination" ); 
    }
}

var consumerA = new SomeConsumer( TextClient.Send ); // sends text messages
var consumerB = new SomeConsumer( MailClient.Send ); // will send emails
1 голос
/ 14 июля 2010

Не делайте методы статичными, создайте интерфейс с помощью метода Send() и реализуйте этот интерфейс на TextClient и MailClient.Теперь вы можете просто внедрить экземпляр, используя интерфейс.

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

0 голосов
/ 14 июля 2010

Я бы так и подумал.Если у вас есть интерфейс как таковой

public interface ISender
{
void Send(string text, string destination);
}

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

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