2009-02-13 3 views
2

Моей наиболее часто используемая мини-картины:Полезной мини-модели (не дизайн модели)

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" } 
          }; 

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

Главное преимущество заключается в том, что у меня нет проблемы с запоминанием для добавления всего правильного кода для каждого случая инструкции коммутатора, я просто добавляю новый элемент в массив 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();    
+2

Ум ... не будет лучше работать в Map/Dictionary здесь? –

+0

Это ужасная, ужасная идея. Карта/Словарь - это намного лучшее решение. –

+0

точка блуждания за вопросы и ответы –

ответ

3

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

3

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

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(); 
} 

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

+0

В C# вы можете просто использовать System.Activator.CreateInstance, чтобы сделать это ... –

+0

hmm ... может быть, не баскар ... –

+0

Я тоже это использовал, но я обнаружил, что это не работает в PHP, ?: не должно иметь достаточно низкого приоритета или что-то в этом роде. – Kip

0

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

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

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

(BTW: Я видел термин «идиома» используется для мини-моделей ...)

+0

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

+0

Прикрепление к тегу не более хрупкое, чем исходный выбор кодировки в инструкции switch. Я предположил, что имена файлов были исправлены или собраны в ресурсы. –

2

В моей последней работе я написал C# версии концепции подкреплений, введенной в C++ Андрея Alexandrescu и Петра Marginean (original article here).

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


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

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

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

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

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

3

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

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

public interface Collection 
{ 
    ... 

    public Iterator iterate(); 
} 

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

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

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.

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

0

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

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

5

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

VideoLookup = new Dictionary<Button, string> { 
    { buttonVideo1, "Video01.flv" }, 
    { buttonVideo2, "Video02.flv" }, 
    { buttonVideo3, "Video03.flv" }, 
    { buttonVideo4, "Video04.flv" }, 
    { buttonVideo4, "Video04.flv" } 
}; 
1

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

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

Будет ли это вызывают у меня утечки памяти в какой-то момент? Я не уверен! Вероятно, это заслуживает вопроса. Ack! Сроки!

+0

Какой язык этот фрагмент кода даже в? – Andrew

+0

C# ................. – Jimmy

+2

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

0

Возможно, это уже лучший способ сделать это (vbEx2005/.Net2.0), но я счел полезным иметь класс родовых делегатов-создателей, которые принимают метод, который принимает некоторые параметры, наряду с значения либо всех, либо всего одного из этих параметров, и дает делегат, который при вызове вызовет указанную функцию с указанными параметрами.В отличие от таких параметров, как 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, "Привет") на объекте, где Foo был объявлен. К сожалению, мне приходится иметь отдельные общие классы и методы для каждого разного количества параметров, которые я хочу поддерживать, но лучше всего вырезать и вставить в один файл, чем иметь дополнительный код, разбросанный по всему миру, чтобы создать соответствующих делегатов.

Смежные вопросы