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

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

Babel のセットアップ
------------------

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

```bash
npm install -g babel-node
```

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

```bash
npm install babel-preset-es2015
```

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

```bash
babel-node --presets es2015 test.js
```

Execute Around Method
---------------------

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

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

Pluggable Behavior
-------------------

```javascript
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
-------------------------------

```javascript
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
------------------------

```javascript
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
----------------------

```javascript
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
----------------

```javascript
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
---------------

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

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

Method Combination
-------------------

```javascript
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]))
```