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