语言集成设计模式

时间:2009-12-09 10:07:54

标签: language-agnostic design-patterns oop

我注意到初学者很难开始使用设计模式。理解设计模式结构需要大量时间。将设计模式应用于您的练习需要花费大量时间。同意,如果你不熟悉它们,你不能第一次看到各种类型的设计模式之间的差异。如果您的类具有合适的名称,则可以部分解决此问题。如果你遗漏了一些编写代码的规则,或者你对设计模式没有那么有经验,你也可以打破你实现的设计图案类结构。编译器可以保护您并帮助您实现接口 - 如果您没有实现接口,则无法编译您的应用程序。这是一种安全可靠的方法。如果编译器在实现设计模式类时也可以保护您?看,很多编程语言都支持“foreach”语句。如果编程语言可以为工厂,桥梁,代理,纪念品等提供支持?如果它可能是真的,你可以使用类似下面的东西来应用抽象和具体的工厂模式(我更喜欢C#作为伪代码的基本语言;假设使用了上下文关键字):

public abstract factory class AF {
    public product AP1 GetProduct1();
    public product AP2 GetProduct2();
};

public concrete factory class CF1 : AF {
    public product CP1 GetProduct1() { ... }
    public product CP2 GetProduct2() { ... }
};

它认为它可以帮助您理解新的源并保持应用程序源代码结构的完整性。你怎么看待这个?

3 个答案:

答案 0 :(得分:5)

如果我理解你所说的话,你认为新语言功能应该克服通常与实现设计模式相关的样板代码的需要。

这已经发生了,这并不是什么新鲜事。

以单身人士为例,这是最着名的模式之一。每个人都知道如何实现它:您声明构造函数private,将对象的单个全局实例保留为static属性,并添加public方法来检索它。

对于概念上非常简单的代码,这里有相当多的代码。

在Scala中,您不需要任何样板来创建单例。为了补充class关键字,Scala有一个object关键字,它声明了一个单例对象:

object MainApp {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

在运行时,将有一个MainApp的单一全局实例。无需使用new实例化它;事实上,你根本不能使用new MainApp

答案 1 :(得分:1)

有一种观点认为,语言中设计模式的存在表明了语言本身设计的弱点,而下一代语言应该从上一代常见的设计模式中学习。 / p>

例如,请参阅Peter Norvigs famous presentation,了解设计模式在动态语言中是不可见的。

事实上,很容易想出已经发生过这个过程的例子 - 正如你所说,foreach循环可以说是嵌入式迭代器,Ruby有一个单独的mixin来继承,任何带有多方法的语言都不需要访问者模式。 Groovy内置了Builders。

您的工厂的具体示例听起来有点像Noop将依赖注入集成到语言规范中。

当然,只有到目前为止,类型检查器才能确保代码的正确性(目前)。将设计模式嵌入到语言中并不会消除对核心概念的熟悉程度,也不会考虑应用程序解决手头的问题。

您的示例很有趣,您建议在语言中添加几个关键字和规则(我不熟悉C#)没有明显的好处。什么“factory”关键字告诉类型检查器(或其他程序员)不清楚将“AF”声明为Java接口的等效物,并将“product”作为其方法的返回类型?

答案 2 :(得分:0)

我认为你正在做点什么。但是你错过了重点(在我看来)是你试图指定一种设计模式,正如MHarris所说,随着时间的推移,它们往往会被弃用或过时,使得语言依赖于它们这么好的主意。

我认为,可能有一个'复合材料'语言,你有两个工件:设计规范语言(与实现语言相结合,不要认为UML)和实现。举个例子,可以这样做:

设计规范:

single public Factory
    methods:
        T Get[T]

请注意,如果这样做,因为设计规范是抽象的(不需要在那里指定低级细节),它可以具有便于编写规范的构造。要知道在规范中你不需要说方法是公共的还是私有的,设计规范(不包括算法伪代码)只关心公开可见的行为,而不是私有的实现细节。

实施:

public class ConcreteFactory : Factory {
    public Product1 GetProduct1() { ... }
    public Product2 GetProduct2() { ... }
};

这里可以使用两种方法:

  1. 编译器可以将设计作为工件,然后检查实现代码是否与其一致。
  2. 编译器或运行时可以提供可以自动生成的部分实现(如单例实现),代码本身可以假设它是单例而不需要重新指定,例如:

    类ConcreteFactory:Factory {

      Product1 GetProduct1 { new ConcreteProduct1 }  
    
      Product2 GetProduct2 { new ConcreteProduct2 }  
    

    }

  3. 请注意,实现可能会忽略更高级别的内容,例如类的可见性和方法的可见性,因为这已在设计级别(DRY)指定。如果你问我,这种类型的语言也必须带有专门的IDE,以便提供有关类型设计的上下文信息。正如Jeff Atwood评论的那样,任何新语言都应该配备专门的IDE。