본문 바로가기
개발 언어 관련/DesignPattern

Design Patterns

by 딩디리링 2012. 1. 2.


퍼온거에요...


Design Patterns


Erich Gamma, Richard Helm, Ralph Johnson, John Vissides 이 4명의 개발자에 의해 
정리된 '디자인패턴'을 the Gang of Four 또는 GoF라고 한다. 자주 사용되는 23개의
디자인 패턴에 대해 알아보면 아래와 같다.


생성에 관한 패턴 구조에 관한 패턴 행동에 관한 패턴
  • Abstract Factory
  • Builder
  • Factory Method
  • Prototype
  • Singleton
  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy
  • Chain of Responsibility
  • Command
  • Interpreter
  • Iterator
  • Mediator
  • Memento
  • Observer
  • State
  • Strategy
  • Template Method
  • Visitor


총 23개의 패턴 중에서 여기서 설명하고자 하는 패턴은 4가지이다.
Singleton, Factory, Decorator, Observer가 그것이다.


Singleton 패턴


싱글턴 패턴은 유일무일한 단 하나의 객체를 생성하는 패턴이다. 
즉, 중복된 것을 제외 하고 유일한 것을 뽑는 패턴이라고 할 수 있다.

그럼 이를 만드는 코드를 보자.
function Logger(){
     if(typeof global_log === 'undefined'){
          global_log = this;
     }
     return global_log;
}

var a = new Logger();
var b = new Logger();
alert(a === b);


위의 패턴의 장점은 시스템에서 오직 한번만 일어나도 되는 것을 물리적으로 제한하는 것이다.
이는 가장 기초적이면서도 자주 사용되는 패턴이므로 책을 통해 확실히 알아두면 좋을 것이다.


Factory 패턴


팩토리 패턴은 객체 생성에 관련된 디자인 패턴이다.
이 팩토리 패턴는 객체 생성하는 부분을 캡슐화를 할 수 있으며, 이를 서브에서 활용할 수 있게 한다.

다음의 예를 보자. 기능적으로 유사한 생성자 함수 3개를 생성하자.
var MYAPP = {};
MYAPP.dom = {};
MYAPP.dom.Text = function(){
     this.insert = function(where){
          var txt = document.createTextNode(this.url);
          where.appendChild(txt);
     };
};
MYAPP.dom.Link = function(){
     this.insert = function(where){
          var link = document.createElement('a');
          link.href = this.url;
          link.appendChild(document.createTextNode(this.url));
          where.appendChild(link);
     };
};
MYAPP.dom.Image = function(){
     this.insert = function(where){
          var im = document.createElement('img');
          im.src = this.url;
          where.appendChild(im);
     };
};


그럼 위의 각각의 생성자 함수를 사용하는 방법은 같다. 
url속성을 지정하고 insert()메소드를 호출한다.
var o = new MYAPP.dom.Image();
o.url = 'http://images.packtpub.com/images/PacktLogoSmall.png';
o.insert(document.body);
var o = new MYAPP.dom.Text();
o.url = 'http://images.packtpub.com/images/PacktLogoSmall.png';
o.insert(document.body);
var o = new MYAPP.dom.Link();
o.url = 'http://images.packtpub.com/images/PacktLogoSmall.png';
o.insert(document.body);


위와 같이 하나의 지정된 url에 해당하는 타입을 모를 경우 3개의 생성자를 모두 실행을 하게 된다.
이를 간편하게 if나 switch문을 이용하여 보자.
var o;
if(type === 'Image'){
     o = new MYAPP.dom.Image();
}
if(type === 'Link'){
     o = new MYAPP.dom.Link();
}
if(type === 'Text'){
     o = new MYAPP.dom.Text();
}
o.url = 'http://....';
o.insert();


위와 같이 작업을 수월히 할 수 있으나, 만약 생성자 함수가 많아지면 이 또한 불편해진다.
이를 위해 하나의 함수를 더 생성해 보자.
MYAPP.dom.factory = fufnction(type){
     return new MYAPP.dom[type];
}

var o = MYAPP.dom.factory(type);
o.url = 'http://...';
o.insert();



Decorator 패턴


데코레이터 패턴은 구조에 관한 디자인 패턴이다. 이는 확장에 의한 구조로써 아래의 예를 보자.
var tree = {};
tree.decorate = function(){
     alert('Make sure the tree won\'t fall');
};

// 그럼 이제 tree에서 확장하게 하는 함수를 작성하자.
tree.getDecoretor = function(deco){
     tree[deco].prototype = this;
     return new tree[deco];
}

// 그럼 확장할 속성들을 만들어보자.
tree.RedBalls = function(){
     this.decorate = function(){
          this.RedBalls.prototype.decorate();
          alert('Put on some red balls');
     }
};
tree.BlueBalls = function(){
     this.decorate = function(){
          this.BlueBalls.prototype.decorate();
          alert('Add blue balls');
     }
};
tree.Angel = function(){
     this.decorate = function(){
          this.Angel.prototype.decorate();
          alert('An angel on the top');
     }
};

// 이 함수들을 실행하자.
tree = tree.getDecorator('RedBalls');
tree = tree.getDecorator('BlueBalls');
tree = tree.getDecorator('Angel');

// 마지막으로 decorate()메소드를 실행하자.
tree.decorate();

위의 메소드를 실행하게 되면 아래의 순서대로 명령문이 띄워진다.

Make sure the tree won't fall
Put on some red balls
Add blue balls
An angel on the top

이런 식으로 확장할 함수들을 추가적으로 생성하고 이 중 선택하고자 하는 함수만을 실행해 붙여줄수 있다.


Observer 패턴


옵저버 패턴에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 
자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의합니다.
다음의 예제를 보자.
var observer = {
	addSubscriber: function(callback){
		this.subscribers[this.subscribers.length] = callback;
	},
	removeSubscriber: function(callback){
		for(var i=0 ; i<this.subscribers.length; i++){
			if(this.subscribers[i] === callback){
				delete(this.subscribers[i]);
			}
		}
	},
	publish: function(what){
		for(var i=0 ; i<this.subscribers.length; i++){
			if(typeof this.subscribers[i] === 'function'){
				this.subscribers[i](what);
			}
		}
	},
	make: function(o){
		for(var i in this){
			o[i] = this[i];
			o.subscribers = [];
		}
	}
};

var blogger = {
	writeBlogPost: function(){
		var content = 'Today is '+new Date();
		this.publish(content);
	}
};

var la_times = {
	newIssue: function(){
		var paper = 'Martians have landed on Earth!';
		this.publish(paper);
	}
};

observer.make(blogger);
observer.make(la_times);

var jack = {
	read: function(what){
		console.log('I just read that '+what);
	}
};
var jill = {
	gossip: function(what){
		console.log('You didn\'t hear it from me, but '+what);
	}
};

blogger.addSubscriber(jack.read);
blogger.addSubscriber(jill.gossip);


>>> blogger.writeBlogPost();
I just read that Today is Mon Jan 12 2009 17:57:11 GMT+0900
You didn't hear it from me, but Today is Mon Jan 12 2009 17:57:11 GMT+0900

>>> blogger.removeSubscriber(jill.gossip);
>>> blogger.writeBlogPost();
I just read that Today is Mon Jan 12 2009 17:57:11 GMT+0900

>>> la_times.addSubscriber(jill.gossip);
>>> la_times.newIssue();
You didn't hear it from me, but Martians have landed on Earth!

이를 통해  blogger와 la_times는 observer로 등록이 된다.

 

 

참고사이트(http://compstat.chonbuk.ac.kr/JavaScript/index.html)



댓글