디자인 패턴
디자인 패턴은 소프트웨어 설계에서 발생하는 문제를 해결하기 위한 일반적인 해결책임. 알고리즘이랑 다른 점은 방법론적으론 제시하지만 실제 구현은 개발자에게 달려있다는 것.
디자인 패턴은 팀 공통적으로 소통할 수 있도록 도와주는 Common Language가 될 수 있음.
단점
패턴은 널리 사용되는 접근 방식을 시스템적으로 체계화한거라 프로젝트의 Context을 적용되는게 아니라 '요점'에 적용되어 비효율적인 해결책이 될 수 있음
이 디자인 패턴을 배워서 응용하려는 과정에서 불필요하게 적용할 수도 있음. 해머를 들면 모든게 박아야할 못처럼 보임!
구조
Creational patterns : 객체 생성 메커니즘에서 유연성과 코드 재사용성을 늘려주는 패턴
Structural patterns: 유연하고 효율적인 구조를 유지하면서 객체와 클래스들을 더 큰 구조로 합치는 패턴
Behavioural patterns : 효과적인 의사소통과 객체간 책임 할당에 관한 패턴
오느을은 항상 어디서 들어봤던 Singleton 패턴을 공부해보자 싱글벙글~
Singleton Problem
Problem: Singleton Problem은 Single Responsiblity Principle(단일 책임 원칙)을 동시에 위반하면서 두 가지 문제 해결함!!
1. 클래스에 인스턴스가 오직 하나만 존재하게 함.
왜? 파일, DB 등의 공유 리소스 접근을 제한하기 위함
어떻게? 객체 생성하고 좀 있다가 새로 객체를 생성하면 새 객체를 주는것이 아니라 이미 있는 것을 반환해줌
Constructor call은 항상 새 object를 줘야하기 때문에 일반적인 생성자에서는 사용할 수 없으.
2. 그 인스턴스에 전역 접근 포인트를 제공해줌.
전역 변수들은 편하기도 하기만 변수들의 내용들을 의도치 않게 덮어쓰거나 앱을 크래시할 수 있어 안전하지 못함
전역변수처럼 Singleton pattern은 프로그램 어디서라도 특정 object를 접근할 수 있도록 해주면서 다른 코드에 의해 인스턴스가 덮여쓰는것을 막아줌
이 문제에는 다른 면도 있는데, 1을 해결해주는 코드가 여러곳에 분산되어있으면 안됨. 한 클래스에 있는게 좋음
싱글톤은 너무 유명해서 하나의 문제만 해결해도 싱글톤이라고 부르는 경우가 잦음.
싱글톤의 구현은 대체로 두가지 스텝으로 구성되어있음
- 기본 생성자를 private로 놓아 다른 객체가 new 연산자를 통해 싱글톤 클래스를 생성하지 않도록 막음
- 생성자 역할을 하는 static method를 만듦. 이 메서드는 private 생성자를 호출하여 객체를 만들고 static field에 저장함. 이 방식으로 부른 객체는 cached object를 반환함
만약 singleton class에 접근한다면, 싱글톤의 static method를 통해서 접근함. 이 메서드가 호출되면 동일한 객체가 반환된다.
// The Database class defines the `getInstance` method that lets
// clients access the same instance of a database connection
// throughout the program.
class Database is
// The field for storing the singleton instance should be
// declared static.
private static field instance: Database
// The singleton's constructor should always be private to
// prevent direct construction calls with the `new`
// operator.
private constructor Database() is
// Some initialization code, such as the actual
// connection to a database server.
// ...
// The static method that controls access to the singleton
// instance.
public static method getInstance() is
if (Database.instance == null) then
acquireThreadLock() and then
// Ensure that the instance hasn't yet been
// initialized by another thread while this one
// has been waiting for the lock's release.
if (Database.instance == null) then
Database.instance = new Database()
return Database.instance
// Finally, any singleton should define some business logic
// which can be executed on its instance.
public method query(sql) is
// For instance, all database queries of an app go
// through this method. Therefore, you can place
// throttling or caching logic here.
// ...
class Application is
method main() is
Database foo = Database.getInstance()
foo.query("SELECT ...")
// ...
Database bar = Database.getInstance()
bar.query("SELECT ...")
// The variable `bar` will contain the same object as
// the variable `foo`.
여기서 Database가 Singleton 구성이며 Application에서 foo와 bar 객체는 동일한 객체를 담고 있다.
사용성
프로그램의 모든 클래스가 사용해야할 단일 인스턴스를 필요로 할떄 굳~
default 생성자를 private로 돌렸기 때문에 특수 생성함수를 제외하고는 객체를 만들수 있는 방법이 없음. 새 객체를 만들거나 있던 객체를 항상 반환함
전역변수에 대해서 엄격히 관리할떄 쓰면 좋아오. 항상 인스턴스가 하나만 있음을 보장함. 근데 이 제한을 조정하고 Singleton Class 인스턴스 생성을 허용할 수도 있음. getInstance만 바꿔주면 됨
장점
- 클래스는 오직 하나의 인스턴스만 있음을 확신
- 그 인스턴스에 전역적으로 접근 가능
- 처음 요청되었을때만 초기화됨
단점
- 단일책임 원칙 위반 - > 한번에 두 문제를 해결함(전역적 접근 + 1클래스 1인스턴스)
- 프로그램의 구성요소가 서로에 대해 너무 잘 아는 문제 등의 나쁜 디자인을 감출수 있음
- 멀티쓰레드 환경에서 특수한 처리를 해줘야 싱글톤 객체를 여러번 안만듦
- 많은 테스트 프레임워크가 mock 객체를 만들때 상속에 의존하므로 싱글턴의 클라이언트 코드를 유닛테스트하는건 어려움. 대부분의 언어에서 정적 메서드 mock하는건 안되므로 싱글턴 mock할 창의적인 방법을 생각해야하는데, 그냥 테스트를 하지 말거나 싱글톤을 사용을 말자
https://refactoring.guru/design-patterns/singleton
Singleton
Real-World Analogy The government is an excellent example of the Singleton pattern. A country can have only one official government. Regardless of the personal identities of the individuals who form governments, the title, “The Government of X”, is a g
refactoring.guru
별도로 검색했을떄 싱글톤의 문제점에 대해서 항상 나오는 말은
- transparency가 퇴색됨 -> 이미 말이 나왔지만 싱글톤을 사용해서 좋을떄와 아닐떄를 구분하는 게 아니라 단순히 간편하니까 (전역변수처럼) 사용하다보면 점차 코드가 의도대로 동작하지 않는 경우가 많아질거임
-디자인의 의존성이 명시적으로 넘겨주는게 아니라 코드 안에 숨겨져있음! 테스트(특히 유닛테스트)를 진행할 수 있는 요건은 주변환경과 결합이 약하기 때문임. 그래서 Mock하기가 편해서 특정 테스트의 목표를 세분화하여 잡기가 쉬움. 근데 싱글톤 쓰면 강하게 연결되어있어서 Mock이 까다로움
'TIL' 카테고리의 다른 글
TIL-2022-05-09 Stacking Context와 Z-index 없이 Stacking (0) | 2022.05.09 |
---|---|
TIL 2022-05-07 Factory Pattern (0) | 2022.05.07 |
TIL 2022-05-03 HTML Details, Summary Tag (0) | 2022.05.03 |
TIL 2022-04-28 monorepo, global css Nextjs 문제 (0) | 2022.04.28 |
TIL 2022-04-27 package-lock, package-manager (0) | 2022.04.27 |