GoF设计模式-您实际使用哪些模式?[关闭]


16

我正在尝试对设计模式领域的同事进行教育。最初的“四人一组”模式有些神秘,所以我想知道是否有所有程序员都应该知道的“基本”模式子集。当我浏览列表时,我想我可能已经使用过-

  • 抽象工厂
  • 工厂方法
  • 辛格尔顿
  • 正面
  • 命令

您实际上在实践中使用了哪些?您将它们用于什么?

链接给那些想要模式列表的人


7
恕我直言,这个问题太含糊,无法进行有益的讨论。您想要每个模式一个答案还是每个模式组合一个答案?
Macke

使用这些模式的某些原因会很有用,否则,您只是在列出概念...想象一下,问一个问题:“您使用什么关键字?” 并收集“ for, if, while...等” 列表-很难衡量那将是多么毫无意义。
ocodo 2011年

1
我不同意Slomojo-我认为知道哪个常用关键字和哪个不使用语言是非常方便的。例如,基类也是如此。
Craig Schwarze

1
对其进行了一些修改-希望现在可以引起更好的讨论。
Craig Schwarze

1
您实际吃哪种水果?我很想知道您希望从这个问题中得到什么。如果您看到3或4个人使用过但没有使用过的模式,那会促使您使用它吗?
Marcie

Answers:


4

这是我在实践中使用或看到的列表:

Singleton-ASP.Net中的应用程序对象就是一个很好的例子。

适配器-连接到数据库通常至少在我的.Net领域中涉及一个Adapter类。

工厂-生成对象的常规方法,尽管我早些时候在一些较旧的经典ASP中看到的更多。

策略-我有一个应用程序,对于每种类型的设备,我都有一个类似的类结构,我将考虑采用这种模式。

外观-在某些方面,它通常类似于将几个系统捆绑在一起的方式,类似于适配器模式。


1
所有有效用途。对于也阅读本文的任何人-请记住,这些模式当然不限于这些。
鲍里斯·扬科夫

5

作者从在实际应用中发现的观察设计中编译了模式。没有人可能会全部使用它们,但是它们都被使用了。


您使用了smithco的是什么?
Craig Schwarze

@CraigS我已经使用了很多。“设计模式”的作者针对每个描述的模式都有一组很好的示例。我能给的最好的建议是花时间彻底阅读这本书。
smithco

3

装饰器

编辑:在几乎超出“琐碎”阶段的每个项目中,最终都有一个IAction接口(细节可能有所不同):

// Programming Language does not matter
interface IAction {
     bool operateOn(Foo* target);
     string getDisplayName(); // useful for debugging and logging
};

下一个小时,我花了很多时间编写了一些很小的,几乎没有意义的类来实现IAction。结合使用时,它们将非常强大且灵活。

例如,LogAction(写入日志并执行IAction),NullAction(不执行任何操作并返回true),ActionList(执行IActions列表并返回布尔值的ANDing)。在某些情况下,AndAction(返回的两个动作该与荷兰国际集团,可能是短路与否)OrActionNotAction是有意义的为好。

尽管从上面的示例的角度来看,从技术上讲,只有LogAction是一个Decorator(另一个不能完全在1个IAction上运行),但是当我制作IActions的LogActions的ActionList时,我仍然认为这是Decorator模式的概括。


你用它来做什么?
Craig Schwarze

1
@CraigS示例可根据要求添加。
Sjoerd

它实际上看起来更像是Decorator和Composite的混合,这很好,并且完美地证明了模式的困难不是来自单独使用它们,而是来自将它们混合在一起:)
Matthieu M.11年

是的,这是经典。它是用命令组合而成的。该样式实际上有一个名称:它被称为“规范”(en.wikipedia.org/wiki/Specification_pattern)。
Martin Wickman

2

我假设您的意思是将问题限制在自己的代码/项目(没有类库和第3方框架)中使用模式。

和其他人一样,我也经常使用Factory模式。然后

  • Singleton:如今已不多了,但有时还是有必要的,通常用于全局配置数据
  • 策略模板方法:经常出现,例如在我们的应用程序中表示不同种类的计算
  • Builder:用于将大型机系统的交易结果编组为输出对象(在某些情况下,它包括大量的文本解析和创建大对象层次结构)
  • Command:我仅在多年前就实现过一次,但是如今在我们的Java项目中,我时不时地使用Callables,我认为这基本上就是Commands

2

我使用了已经提到的许多其他功能(Singleton,Factory,Builder,Command,Strategy等)。

我还没有提到的一个是Flyweight,我经常使用它。我在下面提供了一个示例实现:

/**
 * Flyweight class representing OCR digits.
 * 
 * @author matt
 *
 */
public class Digit {
    /** Static flyweight map containing Digits which have been encountered. **/
    private static Map digits = new HashMap();

    /** The block of text representing Digit. **/
    private String blockRep = null;

    /** A map representing acceptable blocks of characters and the string representation of their
     * numerical equivalents.
     */
    public static final Map VALID_DIGITS;

    /** Enum of valid digits. **/
    public static enum DigitRep {
        ZERO    (   " _ \n" +
                    "| |\n" +
                    "|_|"       ),

        ONE (       "   \n" +
                    "  |\n" +
                    "  |"       ),

        TWO (       " _ \n" +
                    " _|\n" +
                    "|_ "       ),

        THREE   (   " _ \n" +
                    " _|\n" +
                    " _|"       ),

        FOUR    (   "   \n" +
                    "|_|\n" +
                    "  |"       ),

        FIVE    (   " _ \n" +
                    "|_ \n" +
                    " _|"       ),

        SIX     (   " _ \n" +
                    "|_ \n" +
                    "|_|"       ),

        SEVEN   (   " _ \n" +
                    "  |\n" +
                    "  |"       ),

        EIGHT   (   " _ \n" +
                    "|_|\n" +
                    "|_|"       ),

        NINE    (   " _ \n" +
                    "|_|\n" +
                    " _|"       );

        private String blockRep;

        DigitRep(String blockRep) {
            this.blockRep = blockRep;
        }

        @Override
        public String toString() {
            return blockRep;
        }
    }

    static {
        /* Initialize the map of acceptable character blocks. */
        Map tmpMap = new HashMap();
        tmpMap.put( DigitRep.ZERO.toString(),   "0");
        tmpMap.put( DigitRep.ONE.toString(),    "1");
        tmpMap.put( DigitRep.TWO.toString(),    "2");
        tmpMap.put( DigitRep.THREE.toString(),  "3");
        tmpMap.put( DigitRep.FOUR.toString(),   "4");
        tmpMap.put( DigitRep.FIVE.toString(),   "5");
        tmpMap.put( DigitRep.SIX.toString(),    "6");
        tmpMap.put( DigitRep.SEVEN.toString(),  "7");
        tmpMap.put( DigitRep.EIGHT.toString(),  "8");
        tmpMap.put( DigitRep.NINE.toString(),   "9");       
        VALID_DIGITS = Collections.unmodifiableMap(tmpMap);
    }

    /**
     * Private constructor to enforce flyweight/factory pattern.
     * 
     * @param blockRep
     */
    private Digit(String blockRep) {
        this.blockRep = blockRep;
    }

    /**
     * Flyweight factory method to create a Digit object from the "block"
     * representation of the digit.
     * @param blockRep The "block" representation of a digit.  Should look
     * something like:
     * " _ \n"
     * "|_|\n"
     * "|_|"
     * @return A flyweight Digit object representing the digit.
     */
    public static synchronized Digit getDigit(String blockRep) {
        Digit digit = digits.get(blockRep);
        if(digit == null) {
            digit = new Digit(blockRep);
            digits.put(blockRep, digit);
        }

        return digit;
    }

    /**
     * Determines whether or not the digit is valid.
     * @return true if the digit is valid, else false.
     */
    public boolean isValid() {
        return VALID_DIGITS.containsKey(blockRep);
    }

    /**
     * Accessor method to get the block representation of this digit.
     * 
     * @return
     */
    public String getBlockRep() {
        return blockRep;
    }

    @Override
    public String toString() {
        return VALID_DIGITS.containsKey(blockRep) ? VALID_DIGITS.get(blockRep) : "?";
    }
}

1
+1一种鲜为人知但仍然非常有用的模式。
MattDavey 2012年

2

如今,大多数原始的“四人一组”模式仍在使用,但本书中没有其他流行的模式。

查找使用您所用语言的设计模式参考。它们往往更具体,并使用特定的语言功能以更简洁和优雅的方式实现模式。

设计模式的三大资源:

《 Head First设计模式》一书 -选择的语言是Java,但与所有语言都有关。 dofactory设计模式 -带有代码的出色,免费的.net设计模式说明。 PluralSight-设计模式库 -该是有偿的,但是很好,不要将其包括在列表中。


1

好吧,如果您使用诸如ACE之类的通用库,最终使用的资源将超出您的想象。我广泛使用Observer / Observable :-)


1

我至少使用过一个Builder(同一转换器过程可以构建HTML或Excel输出)。

我经常使用模板方法(用于与JDBC相关的任务或抽象的Swing控制器)。

一旦我不得不在基于表单的应用程序中开发许多新功能,那真是一团糟。只有将现有内容重构为基于状态模式的解决方案之后,我才能取得进步。(嗯,大部分)。

我也经常使用命令(Swing Actions)和观察者。

一次,我使用了类似Mememento的解决方案来检测Swing形式的变化。表单会将我比较的(equals())与早期状态进行序列化。


1

我相信我大部分人都是我的事业。我确定我没有使用过的唯一方法是,在我的书中通过多继承实现的适配器模式,因为我不是多继承的忠实拥护者。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.