싱글톤 패턴
싱글톤패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
장점 : 인스턴스 생성에 많은 코스트가 드는 데이터베이스 연결 모듈에 많이 쓰이며 인스턴스 생성을 효율적으로 함(인스턴스 생성할 때 드는 비용 줄어듬), I/O 바운드 작업에 많이 사용
단점 : 의존성이 높아지고 TDD를 할 때 불편함, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야함. 하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 '독립적인' 인스턴스를 만들기 어려움
※ A가 B에 대한 의존성이 있다 → B가 변할 때 A도 변한다는 의미
싱글톤이 아닌 클래스
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
const a = new Rectangle(1, 2);
const b = new Rectangle(1, 2);
console.log(a === b) // false
- Rectangle이라는 하나의 인스턴스 생성 → 하나는 a로 선언, 다른 하나는 다른 인스턴스 기반으로 b로 선언
※ 하나의 클래스지만 개별적인 인스턴스가 생성 (서로 인스턴스가 다름)
싱글톤 패턴 - JS
class Singleton {
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
getInstance() {
return this;
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a === b); // true
- Sigleton 이라는 하나의 인스턴스 생성 -> 이 인스턴스 기반으로 a라는 객체, b라는 객체 (동일한 인스턴스)
DB 연결 모듈
const URL = 'mongodb://localhost:27017/kundolapp'
const createConnection = url => ({"url" : url})
class DB {
constructor(url) {
if (!DB.instance) {
DB.instance = createConnection(url)
}
return DB.instance
}
connect() {
return this.instance
} }
const a = new DB(URL);
const b = new DB(URL);
console.log(a === b) // true
MongoDB 연결 모듈 (mongoose)
Mongoose.prototype.connect = function (uri, options, callback) {
const _mongoose = this instanceof Mongoose ? this : mongoose;
const conn = _mongoose.connection;
return _mongoose._promiseOrCallback(callback, (cb) => {
conn.openUri(uri, options, (err) => {
if (err != null) {
return cb(err);
}
return cb(null, _mongoose);
});
});
};
MySQL 연결 모듈
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
host: "example.org",
user: "kundol",
password: "secret",
database: "승철이디비",
});
pool.connect();
// 모듈 A
pool.query(query, function (error, results, fields) {
if (error) throw error;
console.log("The solution is: ", results[0].solution);
});
// 모듈 B
pool.query(query, function (error, results, fields) {
if (error) throw error;
console.log("The solution is: ", results[0].solution);
});
싱글톤 패턴 - JAVA
1. 클래스안에 클래스(Holder), static이며 중첩된 클래스인 singleInstanceHolder를 기반으로 객체를 선언했기 때문에 한 번만 로드되므로 싱글톤 클래스의 인스턴스는 애플리케이션 당 하나만 존재하며 클래스가 두번 로드되지 않기 때문에 두 스레드가 동일한 JVM에서 2개의 인스턴스를 생성할 수 없음
그렇기 때문에 동기화, 즉 synchronized를 신경쓰지 않아도 됨
2. final 키워드를 통해서 read only 즉, 다시 값이 할당되지 않도록 함
3. 중첩클래스 Holder로 만들었기 때문에 싱글톤 클래스가 로드될 때 클래스가 메모리에 로드되지 않고 어떠한 모듈에서 getInstance()메서드가 호출할 때 싱글톤 객체를 최초로 생성 및 리턴하게 됨
class Singleton {
private static class singleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return singleInstanceHolder.INSTANCE;
}
}
public class HelloWorld {
public static void main(String []args) {
Singleton a = Singleton.getInstance();
Singleton b = Singleton.getInstance();
System.out.println(ahashCode());
System.out.println(b.hashCode());
if (a == b) {
System.out.println(true);
}
}
}
/*
705927765
705927765
true
/*
싱글톤 패턴의 단점
- 생성순서의 영향을 미침 → 단위 테스트는 순서의 영향을 받으면 안됨
const assert = require("assert");
const a = [1, 2, 3];
describe("Array", function () {
describe("#indexOf()", function () {
it("should return -1 when the value is not present", function () {
assert.equal(a.indexOf(4), -1);
a[0] = 4;
});
});
describe("#indexOf()", function () {
it("should return -1 when the value is not present", function () {
assert.equal(a.indexOf(4), -1);
});
});
});
//순서를 바꾸면 ALL PASS
describe("Array", function () {
describe("#indexOf()", function () {
it("should return -1 when the value is not present", function () {
assert.equal(a.indexOf(4), -1);
});
});
describe("#indexOf()", function () {
it("should return -1 when the value is not present", function () {
assert.equal(a.indexOf(4), -1);
a[0] = 4;
});
});
});
* 참고
'CS > 디자인패턴' 카테고리의 다른 글
[CS] 의존성주입(DI, Dependency Injection)과 의존관계역전원칙(DIP, Dependency Inversion Principle) (0) | 2023.09.03 |
---|---|
[CS] 이터레이터 패턴 (0) | 2023.09.02 |
[CS] 팩토리 패턴 (0) | 2023.09.01 |
[CS] 싱글톤 패턴을 구현하는 7가지 방법 (0) | 2023.08.31 |
[CS] 디자인 패턴, 라이브러리와 프레임워크 차이 (0) | 2023.08.29 |
댓글