DEV Community

Daniel Mwakanema
Daniel Mwakanema

Posted on

One Design Pattern Per Day (Day 2)

A little context

A few steps back in time, a client "discovered a way" to make more than what was marketed by a certain pyramid scheme. Essentially, con the con-men.

The scheme has a site through which you can create accounts for a fee and if a certain criteria is met, you get rewards. As expected the whole process builds, you guessed it, a pyramid.

I accepted, mostly due to interest in implementing the solution, :).

NB:

Anything that needs further explanation has a link attached to it.

Approach?

  1. Site has no API-like entity so I chose Headless Browsing using Nightmare.js.
  2. Persistence with MongoDB using the Adjacency List Model.
  3. REST API in Node.js because there is also a React application the client needed.

Problem for the day?

This one is a bit trivial. The requirements specified a number of ways to build the pyramid and under certain conditions the application needs to switch between these ways. Essentially, switch its behavior. So having seen it before I thought I'd use the Strategy Pattern.

For this application I am using JavaScript which is dynamically typed and from my small knowledge does not have constructs like interfaces so we'll follow the let-it-fail ideology in the case that a strategy is given that does not implement what we expect.

How am going I to implement it?

  1. Create Strategies using the Revealing Module Pattern. You could do this using a Function constructor as well by attaching accessible members to this.
  2. Create a Context function that uses simple dependency injection to receive a strategy and alters its behavior with the change in strategy. The Context I assume provides a recognized point of access to our 1..N strategies.

The application then chooses strategies and accesses them through the Context. Again I did not run this code, not sure why.

The strategies:

const StrategyB = _ => {
  //more private members here

  function execute () {
    // do stuff in here
  }

  return {
    execute: execute
  }
}

const StrategyA = _ => {
  // more private members here

  function execute () {
    // do more stuff here
  }

  return {
    execute: execute
  }
}

The context:

  function Context (Strategy) {
    this.strategy = Strategy

    this.execute = _ => { this.strategy.execute() }
    this.setStrategy = strategy => { this.strategy = strategy} 
  }

Usage:

  const context = new Context(A_DEFAULT_STRATEGY_OF_YOUR_CHOICE)
  if (SOMETHING) context.execute()
  else if (SOMETHING_ELSE) {
    context.setStrategy(StrategyA())
    context.execute()
  }
  // ... and the ladder goes on

I had a bit of trouble with this one but to me using this pattern allows me to independently implement each strategy while worrying less about writing messy code. With time I may gain more insight into it.

Top comments (0)