有用的迷你模式(不是设计模式)

发布于 2024-07-13 19:43:25 字数 1244 浏览 5 评论 0原文

我最常用的迷你模式是:

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 中的每个项目进行比较,而不是使用每个按钮都有一个 case 的 switch 语句。 然后,当我找到匹配项时,我启动正确的文件(尽管第二部分的操作“查找”可以是委托或其他任何内容)。

主要好处是我不会遇到记住为每个 switch 语句情况添加所有正确代码的问题,我只需向查找 ArrayList 添加一个新项目。

(是的,我知道使用 ArrayList 不是最好的方法,但它是旧代码。而且我知道每次循环遍历数组并不像使用 switch 语句那么有效,但这段代码不是t 在一个紧密的循环中)

有其他人使用任何迷你模式来节省时间/精力或使代码更具可读性吗? 它们不必只是与 GUI 相关

更新:不要复制此代码,我知道它很糟糕,但我没有意识到有多糟糕。 使用类似这样的东西来代替。

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

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

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

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

青衫负雪 2024-07-20 19:43:25

拜托拜托天哪请使用这个版本。

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

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" }
};
归属感 2024-07-20 19:43:25

您可以创建一个结构体或对象,其中包含按钮引用和表示文件名的字符串,然后是这些内容的列表。 或者,您可以使用字典,这样您自己就可以更轻松地进行操作。 有很多改进的方法。 :)

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

薄荷梦 2024-07-20 19:43:25

关于 switch 的主题,我写了很多这样的东西:

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% 的时间这并不重要。

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. Yeah, it'll be slower because you need to compare each condition but 99% of the time that doesn't matter.

我早已燃尽 2024-07-20 19:43:25

在Java中,我有时发现实现公共接口的私有内部类对于由紧密耦合元素组成的对象非常有帮助。 我已经在使用 Allen Holub 的 视觉代理架构,但除此之外就没有太多了。 据我所知,它没有名字。

例如,假设您有一个可以提供 Iterator 的 Collection 接口:

public interface Collection
{
  ...

  public Iterator iterate();
}

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

如果您有一个实现 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 可以完全访问 Stack 的所有私有方法,并且字段。 同时,Stack.IteratorImpl 对除 Stack 之外的所有人都是不可见的。

堆栈及其迭代器往往是紧密耦合的。 最坏的情况是,将 Stack 的迭代器实现为公共类可能会迫使您破坏 Stack 的封装。 私有内部类可以让你避免这种情况。 无论哪种方式,您都可以避免使用真正的实现细节来污染类层次结构。

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

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:

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. At the same time, Stack.IteratorImpl is invisible to all except Stack.

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. The private inner class lets you avoid this. Either way, you avoid polluting the class hierarchy with something that's really an implementation detail.

乞讨 2024-07-20 19:43:25

在我的上一份工作中,我编写了 Andrei Alexandrescu 和 Petru Marginean 在 C++ 中引入的强制概念的 C# 版本(原始版本文章在这里)。

这真的很酷,因为它允许您将错误处理或条件检查与正常代码交织在一起,而不会破坏流程 - 例如:


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

这将检查第一个参数是否为空,如果为空,则抛出一个 EnforcementException 并将第二个参数作为消息,或者否则返回第一个参数。 有些重载也采用字符串格式化参数,以及允许您指定不同异常类型的重载。

您可能会争辩说,此类事情在 C# 中不太相关,因为运行时检查更好并且已经提供了相当丰富的信息 - 但这种习惯用法可以让您更接近源代码并提供更多信息,同时保持表达能力。

我使用相同的系统进行前后条件检查。

我可能会编写一个开源版本并从此处链接它。

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

This is really cool because it lets you interweave error handling or condition checking in with normal code without breaking the flow - e.g.:


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

I use the same system for Pre and Post condition checking.

I might write an Open Source version and link it from here.

极度宠爱 2024-07-20 19:43:25

因为当我快速编写代码时(截止日期!截止日期!为什么我在 stackoverflow.com?截止日期!),我最终会得到这样的代码:

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

这会在某些时候导致我内存泄漏吗? 我不知道! 这可能值得一个问题。 确认! 截止日期!

for when I'm churning out code fast (deadlines! deadlines! why am I on stackoverflow.com? deadlines!), I wind up with this kind code:

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!

感情洁癖 2024-07-20 19:43:25

对于 Windows 表单,我经常使用 Tag 字段来放置伪命令字符串,以便我可以为一组共享按钮提供一个事件处理程序。 这对于执行几乎相同的操作但已参数化的按钮尤其有效。

在第一个示例中,我将按钮的标签设置为等于视频文件的名称——无需查找。

对于具有某种形式的基于文本的命令处理器来调度操作的应用程序,标签是一个刚刚输入命令处理器的字符串。 效果很好。

(顺便说一句:我见过术语“习语”用于迷你模式......)

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

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. Works nice.

(BTW: I've seen the term "idiom" used for mini-patterns...)

愿得七秒忆 2024-07-20 19:43:25

我在 C# 中开始看到的一个新习惯是使用闭包参数来封装方法运行所需的一些配置或设置。 这样,您就可以控制代码在方法内必须运行的相对顺序。

Martin Fowler 将其称为嵌套闭包: http://www.martinfowler.com/dslwip/嵌套闭包.html

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

锦爱 2024-07-20 19:43:25

也许已经有更好的方法来做到这一点(vbEx2005/.Net2.0),但我发现有一类通用委托创建者很有用,它接受一个带有一些参数的方法,以及所有参数的值或这些参数中除一个之外的所有参数,并生成一个委托,该委托在调用时将使用指示的参数调用指定的函数。 与 ParameterizedThreadStart 这样基于 ParamArray 的东西不同,一切都是类型安全的。

例如,如果我说:

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 的对象上调用 Foo(5, "Hello there") 。 不幸的是,我最终不得不为我想要支持的每个不同数量的参数提供单独的泛型类和方法,但是将所有剪切和粘贴都放在一个文件中比将额外的代码分散在各处来创建要好得多合适的代表。

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. Unlike ParamArray-based things like ParameterizedThreadStart, everything is type-safe.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文