Полезные мини-узоры (не дизайнерские узоры) - PullRequest
2 голосов
/ 13 февраля 2009

Мой наиболее часто используемый мини-шаблон:

VideoLookup = new ArrayList  { new ArrayList { buttonVideo1, "Video01.flv" },
                               new ArrayList { buttonVideo2, "Video02.flv" },
                               new ArrayList { buttonVideo3, "Video03.flv" }, 
                               new ArrayList { buttonVideo4, "Video04.flv" },
                               new ArrayList { buttonVideo4, "Video04.flv" }
                             };

Это означает, что вместо оператора switch с регистром для каждой кнопки я могу вместо этого просто сравнить кнопку, которая была нажата, с каждым элементом в ArrayList. Затем, когда я нашел совпадение, я запускаю правильный файл (хотя действие, которое является второй частью, «поиск» может быть делегатом или чем-то еще).

Основным преимуществом является то, что у меня нет проблемы с запоминанием добавления всего правильного кода для каждого случая оператора switch, я просто добавляю новый элемент в поисковый ArrayList.

(Да, я знаю, использование ArrayList - не лучший способ, но это старый код. И я знаю, что циклический просмотр массива каждый раз не так эффективен, как использование оператора switch, но это код не зациклен)

У кого-нибудь есть какие-нибудь мини-шаблоны, которые они используют, которые экономят время / усилия или делают код более читабельным? Они не обязательно должны быть связаны с графическим интерфейсом .

Обновление: Не копируйте этот код, я знал, что это плохо, но я не осознавал, насколько это плохо. Вместо этого используйте что-то подобное.

Hashtable PlayerLookup = new Hashtable();
PlayerLookup.Add(buttonVideo1, "Video01.flv");
PlayerLookup.Add(buttonVideo2, "Video02.flv");
PlayerLookup.Add(buttonVideo3, "Video03.flv");
PlayerLookup.Add(buttonVideo4, "Video04.flv");

string fileName = PlayerLookup[currentButton].ToString();            

Ответы [ 9 ]

5 голосов
/ 13 июня 2009

пожалуйста, пожалуйста, о боже, используйте эту версию.

VideoLookup = new Dictionary<Button, string> {
    { buttonVideo1, "Video01.flv" },
    { buttonVideo2, "Video02.flv" },
    { buttonVideo3, "Video03.flv" }, 
    { buttonVideo4, "Video04.flv" },
    { buttonVideo4, "Video04.flv" }
};
3 голосов
/ 18 апреля 2009

В Java я иногда нахожу, что частные внутренние классы, которые реализуют открытый интерфейс, могут быть очень полезны для объектов, состоящих из тесно связанных элементов. Я видел этот мини-шаблон (идиома), обсуждаемый в контексте создания пользовательских интерфейсов с архитектурой Visual Proxy Аллена Холуба, но не намного дальше. Насколько я знаю, у него нет названия.

Например, допустим, у вас есть интерфейс Collection, который может предоставить итератор:

public interface Collection
{
  ...

  public Iterator iterate();
}

public interface Iterator
{
  public boolean hasNext();
  public Object next();
}

Если у вас есть стек, который реализует коллекцию, вы можете реализовать его итератор как частный внутренний класс:

public class Stack implements Collection
{
  ...

  public Iterator iterate()
  {
    return new IteratorImpl();
  }

  private class IteratorImpl implements Iterator
  {
    public boolean hasNext() { ... }
    public Object next() { ... }
  }
}

Stack.IteratorImpl имеет полный доступ ко всем закрытым методам и полям Stack. В то же время Stack.IteratorImpl невидим для всех, кроме Stack.

Стек и его итератор будут иметь тесную связь. В худшем случае реализация итератора стека в качестве публичного класса может заставить вас нарушить инкапсуляцию стека. Закрытый внутренний класс позволяет вам избежать этого. В любом случае, вы избегаете загрязнения иерархии классов чем-то, что действительно является деталью реализации.

3 голосов
/ 13 февраля 2009

По поводу переключателей я много пишу такие вещи:

public Object createSomething(String param)
{
    return s == null                          ? new NullObject() :
           s.equals("foo")                    ? new Foo() :
           s.equals("bar")                    ? new Bar() :
           s.equals("baz") || s.equals("car") ? new BazCar() :
                                                new Object();
}

Я думаю, что он выглядит более читабельным по сравнению с обычными инструкциями switch и может выполнять более сложные сравнения. Да, это будет медленнее, потому что вам нужно сравнивать каждое условие, но в 99% случаев это не имеет значения.

3 голосов
/ 13 февраля 2009

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

2 голосов
/ 14 февраля 2009

В моей последней работе я написал C # версию концепции Enforcements, представленную в C ++ Андреем Александреску и Петру Марджиняном ( оригинальная статья здесь ).

Это действительно круто, потому что позволяет вам переплетать обработку ошибок или проверку состояния с нормальным кодом, не нарушая поток - например ::


string text = Enforce.NotNull( myObj.SomeMethodThatGetsAString(), "method returned NULL" );

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

Можно утверждать, что такого рода вещи менее актуальны в C #, потому что проверка во время выполнения лучше и уже достаточно информативна - но эта идиома позволяет вам проверять ближе к источнику и предоставлять больше информации, оставаясь при этом выразительным.

Я использую одну и ту же систему для проверки условий до и после.

Я мог бы написать версию с открытым исходным кодом и связать ее отсюда.

1 голос
/ 13 июня 2009

когда я быстро набираю код (сроки! Сроки! Почему я на stackoverflow.com? Сроки!), Я получаю такой код:

Button1.Click += (o,e) => { DoSomething(foo); };

Это приведет к утечке памяти в какой-то момент? Я не уверен! Это, вероятно, заслуживает вопроса. Ack! Крайние сроки!

0 голосов
/ 27 сентября 2010

Возможно, уже есть лучший способ сделать это (vbEx2005 / .Net2.0), но я нашел полезным иметь класс универсальных создателей делегатов, которые принимают метод, который принимает некоторые параметры вместе со значениями либо всех, либо всех, кроме одного, из этих параметров, и выдает делегат, который при вызове будет вызывать указанную функцию с указанными параметрами. В отличие от вещей на основе ParamArray, таких как ParameterizedThreadStart, все безопасно для типов.

Например, если я скажу:

Sub Foo(param1 As Integer, param2 As String)
    ...
End Sub

...
  Dim theAct as Action(of Integer) = _
      ActionOf(of Integer).NewInv(AddressOf Foo,"Hello there")

  theAct(5)
...

результатом будет вызов Foo (5, «Hello there») для объекта, где Foo был объявлен. К сожалению, мне приходится иметь отдельные общие классы и методы для каждого различного числа параметров, которые я хочу поддерживать, но лучше иметь все вырезки и вставки в одном файле, чем разбрасывать дополнительный код повсюду, чтобы создать соответствующие делегаты.

0 голосов
/ 13 июня 2009

Новая идиома, которую я начинаю видеть в C #, - это использование параметров замыкания, которые инкапсулируют некоторую конфигурацию или настройку, которые должен будет функционировать метод. Таким образом, вы можете контролировать относительный порядок выполнения кода внутри вашего метода.

Мартин Фаулер назвал это вложенным замыканием: http://www.martinfowler.com/dslwip/NestedClosure.html

0 голосов
/ 14 февраля 2009

Для форм Windows я часто использую поле Tag, чтобы поместить строку команды psuedo, чтобы у меня был отдельный обработчик событий для общего набора кнопок. Это особенно хорошо работает для кнопок, которые выполняют почти одинаковые действия, но имеют параметризацию.

В вашем первом примере я бы назначил тег для кнопок равным имени видеофайла - поиск не требуется.

Для приложений, имеющих какой-либо текстовый командный процессор для диспетчеризации действий, тег - это строка, которая просто подается в командный процессор. Работает хорошо.

(Кстати: я видел термин "идиома", используемый для мини-паттернов ...)

...