이 게시글은 기존의 클래스/상속 디자인 패턴에서 작동 위임 디자인 패턴으로 사고방식을 바꾸기 위함입니다.
클래스 지향과 대비하여 객체를 다른 객체에 연결하는 코드 스타일을 OLOO (Objects Linked to Other Objects)라고 지칭하겠습니다. 이 코드 스타일에서 우리는 객체가 다른 객체에 작동을 위임하는 부분만 신경 쓰면 됩니다.
OLOO 스타일 코드의 특징은 다음과 같습니다.
다만, 복수의 객체가 양방향으로 상호 위임을 하면 발생하는 사이클은 허용되지 않습니다.
이제 코드로 객체지향과 작동위임 스타일을 비교해보겠습니다.
function Foo(who) {
this.me = who;
}
Foo.prototype.identify = function() {
return `I am ${this.me}`;
}
function Bar(who) {
Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.speak = function() {
alert(`Hello, ${this.identify()}.`);
}
var b1 = new Bar('b1');
var b2 = new Bar('b2');
b1.speak();
b2.speak();
자식 클래스 Bar는 부모 클래스 Foo를 상속한 뒤 b1와 b2로 인스턴스화하였습니다.
다음은 정확히 같은 기능을 OLOO 스타일 코드로 구현한 코드입니다.
const Foo = {
init: function init(who) {
this.me = who;
},
identify: function identify() {
return `I am ${this.me}`;
}
}
const Bar = Object.create(Foo);
Bar.speak = function speak() {
alert(`Hello, ${this.identify()}.`);
}
const b1 = Object.create(Bar);
b1.init('b1');
const b2 = Object.create(Bar);
b2.init('b2');
b1.speak();
b2.speak();
여기서 중요한 것은 잡다한 것들이 정리되고 단순해졌다는 사실입니다. 생성자, 프로토타입, new 호출을 하면서 클래스처럼 보이게 하려고 헷갈리는 장치들을 쓰지 않고 그냥 객체를 서로 연결해 주기만 하였습니다.
OLOO 관점에서는 Foo가 부모도, Bar가 자식도 아닙니다. Foo는 보통 객체로, 유틸리티 창고 역할을 맡는 것이고 Bar는 그냥 단독으로 존재하는 객체이면서 Foo와 위임 링크를 맺어졌을 뿐이므로 더 간단한 코드 아키텍처가 설계됩니다.
클래스 생성자로는 생성과 초기화를 한 번에 해야 하지만 OLOO 방식처럼 두 단계로 나누어 실행하면 더 유연해집니다.
생성 및 초기화 과정을 굳이 한 곳에 몰아넣고 실행하지 않아도 되니 OLOO는 관심사 분리의 원칙을 더 잘 반영한 패턴입니다.
클래스 인스턴스화나 부모/자식 관계를 억지로 맺을 필요가 없습니다. 또한, 다형성이라는 명목으로 메서드를 똑같은 이름으로 포함하지 않아도 되니 기능을 더 쉽게 이해할 수 있습니다.
위의 코드에서 저는 익명 함수가 아니라 함수에 이름을 지어서 선언하였습니다.
굳이 그렇게 한 이유는 아래의 이유들 때문입니다.