Scala中的复合设计模式?

时间:2011-02-12 18:28:32

标签: java scala composite

在java中,我可以按如下方式实现composite design pattern

interface Component{
    void operation();

}

class Composite implements Component{
    @override
    public void operation(){
       for(Child child in children){
           child.operation();
       }
    }        

    public void add(Component child){//implementation}
    public void remove(Component child){//implementation}
    public void getChild(int index);
 }

 class Leaf implements Component{
      @override
      public void operation(){
         //implementation
      }
 }

如何在scala中编写它?特别是我无法理解如何编写接口并实现它?

4 个答案:

答案 0 :(得分:4)

这样的东西
import scala.collection.mutable.ListBuffer

trait Component{
    def operation():Unit
}

class Composite extends Component{

    val children = new ListBuffer[Component]()

    def operation():Unit = children.foreach {_.operation() }

    def add(child: Component):Unit = children += child
    def remove(child: Component):Unit = children -= child
    def getChild(index:Int) = children(index)
 }:

 class Leaf extends Component {
      def operation():Unit = println("leaf") 
 }

这是一个非常直接的翻译。在Scala中,通常使用不可变的解决方案。另一个区别是,您经常使用模式匹配而不是继承。例如。您可以通过从operation()Component移除Leaf并改为编写

来重写该示例
trait Component{
    def operation():Unit = this match {
      case c:Composite => c.children.foreach(_.operation())
      case leaf:Leaf => println("leaf")  
    }
}

答案 1 :(得分:3)

在Scala中,没有任何具体方法的Trait只是一个界面。所以直接翻译是:

trait Component { def operation(): Unit }

class Composite extends Component {
  def operation() = children foreach { _.operation() }
  def add(child: Component) = ...
  def remove(child: Component) = ...
  def getChild(index: Int) = ...
}

class Leaf extends Component {
  def operation() = ...
}

虽然如果你想要更多惯用的Scala,我会推荐这样的东西作为Composite的定义:

class Composite extends Component {
  def operation() = children foreach { _.operation() }
  def +=(child: Component) = ...
  def -=(child: Component) = ...
  def apply(index: Int) = ...
}

用作:

val comp = new Composite
comp += child1
comp += child2
comp -= child1
val firstChild = comp(0)

如果你想得出一个合乎逻辑的结论,我主张将整个复合结构构建为一个不可变的有向无环图(虽然我很欣赏这通常是不可能的):

case class Composite(children: Component*) extends Component {
  def operation() = children foreach { _.operation() }
}

val comp = Composite(child1, Composite(child2, child3), child4)

答案 2 :(得分:0)

Java中作为接口呈现的功能可以在Scala中编码为特征

trait Component{
    def operation():Unit
}

class Composite extends Component{
    @override
    def operation(){
       for(child<-children)
         child.operation()
    }        

    def add(child:Component){//implementation}
    def remove(child:Component){//implementation}
    def getChild(index:Int){//implementation}
 }

 class Leaf extends Component{
      def operation(){
         //implementation
      }
 }

值得一提的是,traits比Java接口更强大,可以包括实现和接口规范。

答案 3 :(得分:0)

更清洁的不变方式是:

trait Component {
  def operation()
  def +(other: Component): Component = new Composite(this, other)
}

class Leaf(name: String) extends Component {
  override def operation(): Unit = println(name)
}

class Composite(children: Component*) extends Component {
  override def operation(): Unit = children foreach { _.operation() }
}

val c = new Leaf("Tom") + new Leaf("Tim")
c.operation() // Tom Tim