Edited at
LIGincDay 5

知っておきたいデザインパターン 1.モジュールパターン

More than 3 years have passed since last update.

LIGアドベントカレンダー5日目です! こんにちは@Im0_3です。


はじめに

LIGからフロントエンドエンジニアとして働き出して8ヶ月が経ちました。現在はWebアプリケーションの開発・運用を主にしています。その中で設計についていろいろと学ぶことがありました。

そこで、あらためてデザインパターンをちゃんと学びたいと思い、アドベントカレンダーを通してデザインパターンについて自分で学んだことを書いていこうと考えました。

内容に関してはO'ReillyのJavaScriptデザインパターンを参考にしつつ書いてます。

これから定期的に書きながら、自分自身も勉強していこうと思うので、皆さんよろしくお願いします。


モジュールパターンとは

モジュールパターンを使うと一つのオブジェクトにパブリックなプロパティ、メソッドと、プライベートなプロパティ、メソッドを用意することができます。そうすることで他に定義した変数や関数と衝突する危険性を減らすことができます。


実践モジュールパターン

たとえば以下のようなコードがあったとします。

var userModel = {

users: [
{
id: 0,
name: 'tencho'
},
{
id: 1,
name: 'nobisuke'
},
{
id: 2,
name: 'inaba'
}
],
add: function(name){
var user = {
id: userModel.users.length,
name: name
}
userModel.users.push(user);
},
getList: function(){
return userModel.users;
},
getUserById: function(id){
var user = userModel.users.filter(function(user){
return user.id === id;
});
return user[0];
}
};

console.log(userModel.getUserById(1)); //Object {id: 1, name: "nobisuke"}

すべての値がuserModelというオブジェクトに紐付いた形になっています。ただ問題なのはすべてのデータがグローバルから簡単にアクセスすることができてしまうことです。

以下がその例です。

console.log(userModel.getUserById(1)); //Object {id: 1, name: "nobisuke"}

console.log(userModel.users); //[Object, Object, Object]

//グローバルからuserModel.usersを書き換えてしまう
userModel.users = [
{
id: 0,
name: 'hayachi'
},
{
id: 1,
name: 'seito'
},
{
id: 2,
name: 'maroc'
}
];

console.log(userModel.getUserById(1)); //Object {id: 1, name: "seito"}

このようにuserModel.usersに自由にアクセスできるため、簡単に書き換えができてしまいます。


モジュールパターンに書き換える

ではuserModel内のusersというデータを安全に保つため、モジュールパターンで書き換えてみます。

var userModel = (function(){

//private
var users = [
{
id: 0,
name: 'tencho'
},
{
id: 1,
name: 'nobisuke'
},
{
id: 2,
name: 'inaba'
}
];
function add(name) {
var user = {
id: users.length,
name: name
}
userModel.users.push(user);
}
function getList() {
return users;
}
function getUserById(id) {
var user = users.filter(function(user){
return user.id === id;
});
return user[0];
}
return {
add: add,
getList: getList,
getUserById: getUserById
}
})();

console.log(userModel.getUserById(1)); //Object {id: 1, name: "nobisuke"}
console.log(userModel.users); //undefined

このようにすることでuserModel内のusersには外からアクセスすることができなくなりました。これがプライベートな状態です。


モジュールのパターンのポイント

JavaScriptでは関数内で定義したものは外からアクセスできないようになっています。(関数スコープ)

この性質を利用してプライベートな空間を作ります。(クロージャ)

usersという変数はクロージャの中だけに存在していて、外からアクセスすることができません。その代わりその値にアクセスするためにadd、getList、getUserByIdという関数を用意しオブジェクトとして返すことで限定的にアクセスできるようにしています。

こうすることでusersはuserModelに渡されたメソッドでのみでしか操ることができなくなり安全な状態を保ちやすくなります。


まとめ

モジュールパターンは比較的扱いやすく、簡単にプライベートな空間を実現できるのでとても便利です。またモジュールの終わりでどの関数や変数がパブリックにアクセスできるかを指定できるので、可読性が向上します。

明日はバックエンドエンジニアの@_shogo_さんです!