올해 연말 쯤 런칭을 목표로하고 있는 프로젝트를 시작하기전, 회사프로젝트에서 사용할 디자인패턴에 대한 정립을 하기 위해 공부를 해보았다
사용될 앱 전체에서 단일 글로벌 인스턴스를 공유 하는 것이다
인스턴스가 필요할 때, 똑같은 인스턴스를 만들지 않고 기존의 인스턴스를 활용하는 것!
생성자가 여러번 호출되도, 실제로 생성되는 객체는 하나이며 최초로 생성된 이후에 호출된 생성자는 이미 생성한 객체를 반환시키도록 만드는 것이다
싱글톤은 한 번 인스턴스화할 수 있고 전역적으로 액세스할 수 있는 클래스입니다.
이 단일 인스턴스 는 응용 프로그램 전체에서 공유할 수 있으므로 Singleton은 응용 프로그램의 전역 상태를 관리하는 데 적합합니다.
let instance;
let counter = 0;
class Counter {
constructor() {
if (instance) {
throw new Error("You can only create one instance!");
}
instance = this;
}
getInstance() {
return this;
}
getCount() {
return counter;
}
increment() {
return ++counter;
}
decrement() {
return --counter;
}
}
const counter1 = new Counter();
const counter2 = new Counter();
// Error: You can only create one instance!
new 를 통해 새로운 두개의 인스턴스를 만들었지만 하나의 인스턴스만 만들 수 있기때문에 오류가 발생한다
그래서 하나의 인스턴스만 만들 수 있도록 동결해주는 메서드가 있는데 바로 Object.freez
이다
Object.freez
는 사용하는 코드가 singleton을 수정할 수 없도록 한다
고정된 인스턴스의 속성은 추가하거나 수정할 수 없으므로 실수로 Singleton의 값을 덮어쓸 위험이 줄어든다
let instance;
let counter = 0;
class Counter {
constructor() {
if (instance) {
throw new Error("You can only create one instance!");
}
instance = this;
}
getInstance() {
return this;
}
getCount() {
return counter;
}
increment() {
return ++counter;
}
decrement() {
return --counter;
}
}
const singletonCounter = Object.freeze(new Counter());
export default singletonCounter;
팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정하게 만드는 패턴이다.
팩토리 패턴은 객체지향 디자인 패턴이다
팩토리 패턴은 비교적 복잡한 객체를 생성하는 경우에 유용할 수 있다.
key와 value의 값이 특정 환경이나 구성에 따라 달라질 수 있으며 팩토리 패턴을 사용하면 사용자가 정의한 key와 value의 값을 포함하는 새 객체를 쉽게 생성할 수 있다.
const createUser = ({ firstName, lastName, email }) => ({
firstName,
lastName,
email,
fullName() {
return `${this.firstName} ${this.lastName}`;
}
});
const user1 = createUser({
firstName: "John",
lastName: "Doe",
email: "john@doe.com"
});
const user2 = createUser({
firstName: "Jane",
lastName: "Doe",
email: "jane@doe.com"
});
console.log(user1);
console.log(user2);
개인적으로는 이 패턴을 주로 사용해서 가장 익숙한 패턴이다
로직을 수행하는 컴포넌트와, markup을 통해 ui를 보여주는 컴포넌트가 분리된 패턴이다
export default class DogImagesContainer extends React.Component {
constructor() {
super();
this.state = {
dogs: []
};
}
componentDidMount() {
fetch("https://dog.ceo/api/breed/labrador/images/random/6")
.then(res => res.json())
.then(({ message }) => this.setState({ dogs: message }));
}
render() {
return <DogImages dogs={this.state.dogs} />;
}
}
import React from "react";
export default function DogImages({ dogs }) {
return dogs.map((dog, i) => <img src={dog} key={i} alt="Dog" />);
}
프록시(Proxy)를 번역하면 대리자, 대변인의 의미를 갖고 있다.
즉, 프록시에게 어떤 일을 대신 시키는 것이다.
어떤 객체를 사용하고자 할때, 객체를 직접적으로 참조하는 것이 아닌 해당 객체를 대항하는 객체를 통해 대상 객체에 접근하는 방식을 사용하면 해당 객체가 메모리에 존재하지 않아도 기본적인 정보를 참조하거나 설정할 수 있고, 실제 객체의 기능이 필요한 시점까지 객체의 생성을 미룰 수 있다.
const person = {
name: "John Doe",
age: 42,
nationality: "American"
};
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${obj[prop]}`);
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
obj[prop] = value;
return true;
}
});
personProxy.name;
personProxy.age = 43;
// The value of name is John Doe
// Changed age from 42 to 43
proxy 처리하는 메서드 중 가장 많이 사용하는것은 get
과 set
이 있다
get
은 값을 가져올때 사용한다
set
은 값을 수정할때 사용한다