Search code examples
javascalacomposite

Composite design pattern in Scala?


In java I can implement the composite design pattern as follows:

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

How can I write it in scala? In particular I am having trouble understanding how to write an interface and implement it?


Solution

  • In Scala, a Trait without any concrete methods is just an interface. So a direct translation would be:

    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() = ...
    }
    

    Though if you want more idiomatic Scala, I'd recommend something like this as a definition for Composite:

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

    To be used as:

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

    If you want to take this to a logical conclusion, I'd advocate building the whole composite structure as an immutable Directed Acyclic Graph (though I appreciate that this often isn't possible):

    case class Composite(children: Component*) extends Component {
      def operation() = children foreach { _.operation() }
    }
    
    val comp = Composite(child1, Composite(child2, child3), child4)