1

I'm trying to implement the Builder design pattern in a Jenkins pipeline shared library. Say I have the following file structure and pseudo-code (to only illustrate the concept I'm after)

src/com/company/builders/
                        /Builder.groovy
                        /WidgetXBuilder.groovy
                        /WidgetYBuilder.groovy

Builder.groovy has

package com.company.builders

abstract class AbstractBuilder {
  protected String part0 = null
  protected String part1 = null
  protected String widget = null
}

// Implement in Widget builder classes
def buildWidget(final String p0, final String p1) {
}

// Used by any Widget concrete class
def getWidget() {
  return widget
}

WidgetXBuilder.groovy has

package com.company.builders

class WidgetXBuilder extends AbstractBuilder {
}

// Overload buildWidget()
def buildWidget(final String p0, final String p1) {
  widget = p0 + p1
}

Similarly, WidgetYBuilder.groovy has

package com.company.builders

class WidgetYBuilder extends AbstractBuilder {
}

// Overload buildWidget()
def buildWidget(final String p0, final String p1) {
  widget = p0 - p1
}

Now I simply want a client to do this. Note my-shared-library is a shared library that I set up in my Jenkins system configuration that has the Git repo of above file structure.

@Library('my-shared-library') _
import com.company.builders.Builder
import com.company.builders.WidgetXBuilder
import com.company.builders.WidgetYBuilder

// Build WidgetX
Builder widgetx = new WidgetXBuilder()
widgetx.buildWidget("part0", "part1") // Build a WidgetX widget
widgetx.getWidget() // get the WidgetX widget

// Build WidgetY
Builder widgety = new WidgetYBuilder()
widgety.buildWidget("part0", "part1") // Build a WidgetY widget
widgety.getWidget() // get the WidgetY widget

Can I achieve this with shared libraries? That is, implement the concept of encapsulation, inheritance, and polymorphism using a shared library? How? TIA

1

1 Answer 1

1

Yes, The structure provided in the question is correct.

With the setup provided above, it will achieve encapsulation through the use of an abstract base class (AbstractBuilder), inheritance by extending the base class in the widget builder classes (WidgetXBuilder and WidgetYBuilder), and polymorphism by overriding the buildWidget method in each builder class.

The only change would be to use using def widgetx = new WidgetXBuilder() instead of Builder widgetx = new WidgetXBuilder(), it allows for flexibility and dynamic typing in Groovy.

This means that the type of the variable widgetx is determined by the type of the object created on the right side of the assignment (new WidgetXBuilder() in the code provided in your question).

Here is an example pipeline (do not need to import com.company.builders.WidgetXBuilder etc. explicitly in your pipeline script if you are using the shared library):

@Library('my-shared-library') _

def buildWidget(AbstractBuilder builder, String part0, String part1) {
  builder.buildWidget(part0, part1)
  return builder.getWidget()
}

pipeline {
  agent any
  
  stages {
    stage('Build Widgets') {
      steps {
        script {
          def widgetX = buildWidget(new com.company.builders.WidgetXBuilder(), "part0", "part1")
          echo "WidgetX: ${widgetX}"
          
          def widgetY = buildWidget(new com.company.builders.WidgetYBuilder(), "part0", "part1")
          echo "WidgetY: ${widgetY}"
        }
      }
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.