leodutra
7/12/2017 - 6:16 PM

Specification pattern implemented on JavaScript

Specification pattern implemented on JavaScript


function Specification() {}

Specification.prototype = {
  isSatisfiedBy: function() { 
    return false
  },
  and: function(spec) {
    return new AndSpecification(this, spec)
  },
  andNot: function(spec) {
    return new AndNotSAndSpecification(this, spec)
  },
  or: function(spec) {
    return new OrSAndSpecification(this, spec)
  },
  orNot: function(spec) {
    return new OrNotSAndSpecification(this, spec)
  },
  not: function(spec) {
    return new NotSpecification(spec)
  }
}


// Specification subclasses ---------------------------------------

function AndSpecification(specA, specB) { 
  this.a = specA
  this.b = specB
}
function AndNotSpecification(specA, specB) { 
  this.a = specA
  this.b = specB
}
function OrSpecification(specA, specB) { 
  this.a = specA
  this.b = specB
}
function OrNotSpecification(specA, specB) { 
  this.a = specA
  this.b = specB
}
function NotSpecification(specA) { 
  this.a = specA
}

// Prototyping

AndSpecification.prototype    = new Specification()
AndNotSpecification.prototype = new Specification()
OrSpecification.prototype     = new Specification()
OrNotSpecification.prototype  = new Specification()
NotSpecification.prototype    = new Specification()


// isSatisfiedBy implementations -----------------------------------

AndSpecification.prototype.isSatisfiedBy = function(candidate) {
  const a = this.a
  const b = this.b
  return a && a.isSatisfiedBy && b && b.isSatisfiedBy &&
    a.isSatisfiedBy(candidate) && b.isSatisfiedBy(candidate)
}

AndNotSpecification.prototype.isSatisfiedBy = function(candidate) {
  const a = this.a
  const b = this.b
  return a && a.isSatisfiedBy && b && b.isSatisfiedBy &&
    a.isSatisfiedBy(candidate) && !b.isSatisfiedBy(candidate)
}

OrSpecification.prototype.isSatisfiedBy = function(candidate) {
  const a = this.a
  const b = this.b
  return a && a.isSatisfiedBy && b && b.isSatisfiedBy &&
    a.isSatisfiedBy(candidate) || b.isSatisfiedBy(candidate)
}

OrNotSpecification.prototype.isSatisfiedBy = function(candidate) {
  const a = this.a
  const b = this.b
  return a && a.isSatisfiedBy && b && b.isSatisfiedBy &&
    a.isSatisfiedBy(candidate) || !b.isSatisfiedBy(candidate)
}

NotSpecification.prototype.isSatisfiedBy = function(candidate) {
  const a = this.a
  return a && a.isSatisfiedBy && !a.isSatisfiedBy(candidate)
}