简体   繁体   English

有用的迷你图案(不是设计图案)

[英]Useful mini patterns (not design patterns)

My most used mini pattern is: 我最常用的迷你图案是:

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

This means that rather than a switch statement with a case for each button I can instead just compare the button that was clicked with each item in the ArrayList. 这意味着,不是每个按钮都有一个case的switch语句,而是只需将单击的按钮与ArrayList中的每个项目进行比较。 Then when I've found a match I launch the correct file (although the action that's the 2nd part the "lookup" could be a delegate or anything else). 然后,当我找到匹配时,我启动了正确的文件(尽管第二部分“查找”的操作可能是委托或其他任何事情)。

The main benefit is that I don't have the problem of remembering to add all the correct code for each switch statement case, I just add a new item to the lookup ArrayList. 主要的好处是我没有记住为每个switch语句添加所有正确代码的问题,我只是在查找ArrayList中添加一个新项。

(Yes I know using an ArrayList isn't the best way to go, but it's old code. And I know that looping through an array each time isn't as efficient as using a switch statement, but this code isn't in a tight loop) (是的,我知道使用ArrayList不是最好的方法,但它是旧的代码。而且我知道每次循环遍历数组不如使用switch语句那么高效,但是此代码不在紧环)

Does anyone else have any mini-patterns they use that save time/effort or make code more readable? 是否有其他人使用任何迷你图案可以节省时间/精力或使代码更具可读性? They don't have to just be GUI related . 它们不必仅与GUI相关

Update: Don't copy this code, I knew it was bad, but I didn't realise how bad. 更新:不要复制这段代码,我知道这很糟糕,但我没有意识到有多糟糕。 Use something like this instead. 请改用这样的东西。

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

please please please omg use this version. 请请使用此版本。

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

You could just create a struct or object that has a button reference and a string representing the file name and then a List of these things. 您可以创建一个结构或对象,该结构或对象具有按钮引用和表示文件名的字符串,然后是这些事物的列表。 Or, you could just use a Dictionary and make it even easier on yourself. 或者,你可以使用一个词典,让自己更容易。 Lots of ways to improve. 有很多方法可以改进。 :) :)

On the subject of switches, I write this kind of thing a lot: 关于开关的主题,我写了很多这样的东西:

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

I think it looks more readable compared to regular switch statements and has the ability to have more complex comparisons. 我认为与常规switch语句相比,它看起来更具可读性,并且能够进行更复杂的比较。 Yeah, it'll be slower because you need to compare each condition but 99% of the time that doesn't matter. 是的,它会慢一点,因为你需要比较每个条件,但99%的时间无关紧要。

In Java, I sometimes find that private inner classes which implement a public interface can be very helpful for objects composed of tightly-coupled elements. 在Java中,我有时会发现实现公共接口的私有内部类对于由紧耦合元素组成的对象非常有用。 I've seen this mini-pattern (idiom) discussed in the context of creating UIs with Allen Holub's Visual Proxy architecture, but not much beyond that. 我已经看到了在使用Allen Holub的Visual Proxy架构创建UI的背景下讨论的这种迷你模式(成语),但除此之外没有多少。 As far as I know it doesn't have a name. 据我所知,它没有名字。

For example, let's say you have a Collection interface that can provide an Iterator: 例如,假设您有一个可以提供迭代器的Collection接口:

public interface Collection
{
  ...

  public Iterator iterate();
}

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

If you have a Stack that implements Collection, then you could implement its Iterator as a private inner class: 如果你有一个实现Collection的Stack,那么你可以将它的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 has complete access to all of Stack's private methods and fields. Stack.IteratorImpl可以完全访问Stack的所有私有方法和字段。 At the same time, Stack.IteratorImpl is invisible to all except Stack. 同时,除了Stack之外,Stack.IteratorImpl对所有人都是不可见的。

A Stack and its Iterator will tend to be tightly coupled. 堆栈及其迭代器将倾向于紧密耦合。 Worst case, implementing Stack's Iterator as a public class might force you to break Stack's encapsulation. 最糟糕的情况是,将Stack的Iterator实现为公共类可能会迫使您破坏Stack的封装。 The private inner class lets you avoid this. 私有内部类可以让你避免这种情况。 Either way, you avoid polluting the class hierarchy with something that's really an implementation detail. 无论哪种方式,您都可以避免使用真正的实现细节来污染类层次结构。

In my last job I wrote a C# version of the Enforcements concept introduced in C++ by Andrei Alexandrescu and Petru Marginean ( original article here ). 在我上一份工作中,我编写了由Andrei Alexandrescu和Petru Marginean在C ++中引入的Enforcements概念的C#版本( 原文在这里 )。

This is really cool because it lets you interweave error handling or condition checking in with normal code without breaking the flow - eg: 这真的很酷,因为它允许您使用普通代码交错错误处理或条件检查而不会破坏流程 - 例如:


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

This would check if the first argument is null, throw an EnforcementException with the second argument as the message if it is, or return the first argument otherwise. 这将检查第一个参数是否为null,如果是,则抛出带有第二个参数的EnforcementException作为消息,否则返回第一个参数。 There are overloads that take string formatting params too, as well as overloads that let you specify a different exception type. 还有重载采用字符串格式化参数,以及允许您指定不同异常类型的重载。

You could argue that this sort of thing is less relevant in C# because the runtime checking is better and already quite informative - but this idiom lets you check closer to the source and provide more information, while remaining expressive. 您可能会认为这种事情在C#中不太相关,因为运行时检查更好并且已经非常有用 - 但是这个习惯用法可以让您更接近源并提供更多信息,同时保持表达。

I use the same system for Pre and Post condition checking. 我使用相同的系统进行前后条件检查。

I might write an Open Source version and link it from here. 我可能会写一个开源版本并从这里链接它。

for when I'm churning out code fast (deadlines! deadlines! why am I on stackoverflow.com? deadlines!), I wind up with this kind code: 因为当我快速编写代码时(最后期限!截止日期!为什么我在stackoverflow.com上?截止日期!),我最后得到了这样的代码:

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

Will this cause me memory leaks at some point? 这会在某些时候导致我的内存泄漏吗? I'm not sure! 我不确定! This probably deserves a question. 这可能值得一个问题。 Ack! 确认! Deadlines! 截止日期!

Perhaps there's already a better way of doing this (vbEx2005/.Net2.0), but I've found it useful to have a class of generic delegate-creators which accept a method that takes some parameters, along with the values of either all, or all but one, of those parameters, and yields a delegate which, when invoked, will call the specified function with the indicated parameters. 也许已经有了更好的方法(vbEx2005 / .Net2.0),但我发现有一类通用委托创建者接受一个带有一些参数的方法,以及所有参数的值都很有用。 ,或者除了一个参数之外的所有参数,并产生一个委托,当被调用时,它将使用指示的参数调用指定的函数。 Unlike ParamArray-based things like ParameterizedThreadStart, everything is type-safe. 与基于ParamArray的东西(如ParameterizedThreadStart)不同,一切都是类型安全的。

For example, if I say: 例如,如果我说:

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)
...

the result will be to call Foo(5, "Hello there") on object where Foo was declared. 结果将是在声明Foo的对象上调用Foo(5,“Hello there”)。 Unfortunately, I end up having to have separate generic classes and methods for every different number of parameters I want to support, but it's nicer to have all the cut-and-paste in one file than to have extra code scattered about everywhere to create the appropriate delegates. 不幸的是,我最终必须为我想要支持的每个不同数量的参数设置单独的泛型类和方法,但是将所有剪切和粘贴放在一个文件中比在每个地方散布额外的代码以创建适当的代表。

For Windows forms I'll often use the Tag field to put a psuedo-command string so that I can have a single event handler for a shared set of buttons. 对于Windows窗体,我经常使用Tag字段来放置一个伪命令字符串,这样我就可以为一组共享按钮设置一个事件处理程序。 This works especially well for buttons that do pretty much the same thing but are parameterized. 这对于完全相同但参数化的按钮特别有效。

In your first example, I would set the Tag for the buttons equal to the name of the video file -- no lookup required. 在第一个示例中,我将按钮的Tag设置为等于视频文件的名称 - 不需要查找。

For applications that have some form of text-based command processor for dispatching actions, the Tag is a string that is just fed into the command processor. 对于具有某种形式的基于文本的命令处理器用于调度操作的应用程序,Tag是一个刚刚送入命令处理器的字符串。 Works nice. 工作得很好。

(BTW: I've seen the term "idiom" used for mini-patterns...) (顺便说一句:我看过用于迷你图案的“成语”一词......)

A new idiom that I'm beginning to see in C# is the use of closure parameters that encapsulate some configuration or setup that the method will need to function. 我在C#中开始看到的一个新习惯用法是使用闭包参数来封装该方法需要运行的一些配置或设置。 This way, you can control the relative order that code must run from within your method. 这样,您就可以控制代码必须在方法中运行的相对顺序。

This is called a nested closure by Martin Fowler: http://www.martinfowler.com/dslwip/NestedClosure.html 这被称为Martin Fowler的嵌套闭包: http//www.martinfowler.com/dslwip/NestedClosure.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM