LoginSignup
15
12

More than 5 years have passed since last update.

クロージャデザインパターン

Last updated at Posted at 2015-12-04

クロージャの練習のために、Closure Design Patterns の記事で紹介されている Groovy のコードを JavaScript に書き換えてみました。Groovy、Scala、Java の書籍を書いている Venkat Subramaniam さんのプレゼン資料が元ネタです。ES2015 で導入された const とアロー関数を使ったスタイルに取り組んでみました。

Babel のセットアップ

ターミナルでコードを実行するために babel-node をインストールします。

npm install -g babel-node

ES2015 を利用するために babel-preset-es2015 をローカルにダウンロードします。

npm install babel-preset-es2015

スクリプトを実行する際にオプションの --presets es2015 を指定します。

babel-node --presets es2015 test.js

Execute Around Method

const operations = (closure) => {
  console.log('Open')
  closure()
  console.log('Close')
}

operations(() => console.log('Operation'))

Pluggable Behavior

const selectValues = (number, closure) => {
  let list = []

  for (let i = 0; i < number; i++) {
    if (closure(i)) {
      list.push(i)
    }
  }

  return list 
}

var ret = selectValues(10, n => n % 2 == 0)
console.log(ret)

Iterator Pattern

const listNumbers = closure => {
  for (let i = 0; i < 4; i++) {
    closure(i)
  }
}

listNumbers(n => {
  if (n < 3) {
    console.log(n + ' は小さい数値')
  } else {
    console.log(n + ' は大きな数値')
  }
})

Dynamical Conditional Execution

const isAdmin = user => {
  return ['foo', 'bar'].indexOf(user) > -1
}

const greet = (user, successClosure, failClosure) => {
  if (isAdmin(user)) {
    successClosure()
  } else {
    failClosure()
  }
}

greet('foo',
  () => { console.log('Hi Admin!') },
  () => { console.log('Hello User') }
)

Template Method Pattern

const withCustomer = (id, closure) => {
  let customer = getCustomer(id)
  closure(customer)
}

const getCustomer = id => {
  let customers = [
    { id: 1 , name: 'foo'},
    { id: 2 , name: 'bar'}
  ]

  for (let customer of customers) {
    if (id === customer.id) {
      return customer
    }
  }

  return {id:null, id: null};
}

withCustomer(1, customer => {
  console.log('Found customer ' + customer.name)
})

Loan Pattern

省略

Command Design Pattern

let count = 0
let commands = []

for (let i = 0; i < 10; i++) {
  commands.push(() => count++)
}

console.log('count is initially ' + count)

commands.forEach(cmd => {
  cmd()
})

console.log('did all commands, count is ' + count)

Strategy Pattern

const calcMult = (n, m) => n * m

const calcAdds = (n, m) => {
  let result = 0

  for (let i = 0; i < n; i++) {
    result += m
  }

  return result
}

const calcStrategies = [calcMult, calcAdds]
calcStrategies.forEach(calc => {
  console.log(10 === calc(5, 2))
})

Factory Pattern

const adder = (x, y) => x + y
const incrementer = adder.bind(null, 1)

console.log(5 === incrementer(4))

Method Combination

const sum = arr => arr.reduce((acc, value) => acc + value)
const first2 = arr => arr.slice(0, 2)
const take2andAdd = n => sum(first2(n))

console.log(3 === take2andAdd([1, 2, 3, 4, 5]))
15
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12