가장 많이 사용되는 Builder,Observer,Factory,Singleton 에 대해 알아보려 한다!!
GoF 중 생성 패턴에 속하며, 객체를 생성할 때 유용하게 사용하는 디자인패턴이다.
기존에 생성자를 이용하여 객체를 생성하는데 생길 수 있는 문제를 보완하기 위해 사용되어 지며, 객체의 Optional한 속성이 많을수록 빌더패턴이 더욱 유용해진다.
builder패턴은 dot(.)체인 문법을 사용한다.
장점
단점
객체 수정이 불가능하기 때문에, 필요에 따라 새로운 객체를 계속 생성해야한다.
그런데 우리가 평소에 사용하던 롬복의 @Builder 애노테이션으로 쉽게 사용할 수 있다.
package WeGoTogether.wegotogether.entity;
// Effective Java의 Builder Pattern
public class HereWeGo {
private final String frontend;
private final String backend;
private final String song;
private final String jung;
private final String kim;
public static class Builder {
// Required parameters(필수 인자)
private final String frontend;
private final String backend;
// Optional parameters - initialized to default values(선택적 인자는 기본값으로 초기화)
private String song ="Songhayoung";
private String jung="Jungjuhyeon";
private String kim="Kimminchan";
public Builder(String frontend, String backend) {
this.frontend = frontend;
this.backend = backend;
}
public Builder Song(String val) {
song = val;
return this; // 이렇게 하면 . 으로 체인을 이어갈 수 있다.
}
public Builder Jung(String val) {
jung = val;
return this;
}
public Builder Kim(String val) {
kim = val;
return this;
}
public HereWeGo build() {
return new HereWeGo(this);
}
}
private HereWeGo(Builder builder) {
frontend = builder.frontend;
backend = builder.backend;
song = builder.song;
jung = builder.jung;
kim = builder.kim;
}
}
이렇게 설정을 하면 Main에서 밑에와 같이 사용이 가능하다.
package WeGoTogether.wegotogether.entity;
public class Main {
HereWeGo hereWeGo = new HereWeGo
.Builder("web,flutter","spring")
.Song("flutterMaster")
.Jung("springMaster")
.Kim("webMaster")
.build();
}
그런데 우리가 평소에 사용하던 롬복의 @Builder 애노테이션으로 쉽게 사용할 수 있다.
@Builder
public static ParticipateDtoRes.participateRes participateDto (Participate participate){
return ParticipateDtoRes.participateRes.builder()
.nickName(participate.getUser().getNickName()) // user를 가져와 다시 nickname을 가져옴
.liked(participate.getLiked())
.is50Up(participate.getIs_50up())
.isBestUp(participate.getIs_bestup())
.participateTime(participate.getParticipateTime())
.build();
}
Observer Pattern은 객체 간에 일대다 관계를 정의하는 디자인 패턴 중 하나이다. 이 패턴은 객체들 사이에 느슨한 결합을 제공하며, 객체의 상태 변화에 대한 다른 객체들의 자동 업데이트를 가능하게 한다.
Observer Pattern은 Subject(주체)와 Observer(관찰자)로 구성된다.Subject 객체는 상태를 가지며, 상태가 변경되었을 때 Observer들에게 알림을 보냅니다. Observer 객체는 Subject 객체의 상태를 관찰하며, 상태가 변경될 때마다 업데이트를 받는다.
장점
단점
느슨한 결합(Loose Coupling)
두 객체가 느슨하게 결합되어 있다는 것은, 그 둘이 상호작용을 하긴 하지만 서로에 대해 잘 모르는 것을 의미합니다. 옵저버 패턴에서는 주제와 옵저버가 느슨하게 결합되어 있는 객체 디자인을 제공합니다.
느슨한 결합의 장점은 다음과 같습니다.
//Observer 인터페이스는 Observer 역할을 하는 객체가 구현해야 하는 메서드를 정의합니다. 이 인터페이스는 다음과 같이 구성됩니다.
package WeGoTogether.wegotogether.entity;
public interface Observer {
void update(int member);
}
Subject 인터페이스는 Subject 역할을 하는 객체가 구현해야 하는 메서드를 정의합니다. 이 인터페이스는 다음과 같이 구성됩니다.
package WeGoTogether.wegotogether.entity;
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
Subject 클래스는 Subject 인터페이스를 구현하며, 상태를 저장하고 Observer 객체들을 등록하고 삭제하는 메서드를 구현합니다. 이 클래스는 다음과 같이 구성됩니다.
package WeGoTogether.wegotogether.entity;
import java.util.ArrayList;
import java.util.List;
public class HereWeGoData implements Subject {
private List<Observer> observers;
private int member;
public HereWeGoData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
int i = observers.indexOf(observer);
if (i >= 0) {
observers.remove(i);
}
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(member);
}
}
public void setMember(int member) {
this.member = member;
measurementsChanged();
}
public void measurementsChanged() {
notifyObservers();
}
}
Observer 클래스는 Observer 인터페이스를 구현하며, Subject 객체의 상태가 변경될 때마다 업데이트를 받는 메서드를 구현합니다. 이 클래스는 다음과 같이 구성됩니다.
package WeGoTogether.wegotogether.entity;
public class HereWeGoObserver implements Observer {
private float member;
public void update(int member) {
this.member = member;
display();
}
public void display() {
System.out.println("Current temperature: " + member);
}
public static void main(String[] args){
HereWeGoData hereWeGoData = new HereWeGoData();
HereWeGoObserver hereWeGoObserver = new HereWeGoObserver();
hereWeGoData.registerObserver(hereWeGoObserver);
hereWeGoData.setMember(12);
hereWeGoData.setMember(13);
}
}
참고자료
방리님 블로그
팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정하게 만드는 패턴이다.
객체는 속성과 함수가 변경, 또는 추가 될 수 있다. 이에 따라 객체의 생성을 담당하는 코드는 변경의 가능성이 높다. 객체의 생성을 담당하는 클래스를 한 곳에서 관리하여 결합도를 줄이기 위하여 팩토리 패턴이 나타나게 된 것이다.
장점
단점
생성자를 서브클래스에 작성
package WeGoTogether.wegotogether.entity.FactoryPattern;
public interface HereWeGo {
void part();
}
spring 클래스 작성
package WeGoTogether.wegotogether.entity.FactoryPattern;
public class Spring implements HereWeGo{
@Override
public void part(){
System.out.println("Spring의 HereWego 메소드");
}
}
web 클래스 작성
package WeGoTogether.wegotogether.entity.FactoryPattern;
public class Web implements HereWeGo{
@Override
public void part(){
System.out.println("Web의 part 메소드");
}
}
flutter 클래스 작성
package WeGoTogether.wegotogether.entity.FactoryPattern;
public class Flutter implements HereWeGo{
@Override
public void part(){
System.out.println("Flutter의 part 메서드");
}
}
package WeGoTogether.wegotogether.entity.FactoryPattern;
public class PartFactory {
public HereWeGo getPart(String partType) {
if(partType == null){
return null;
}
if(partType.equals("Web")){
return new Web();
}
else if(partType.equals("Spring")){
return new Spring();
}
else if(partType.equals("Flutter")){
return new Flutter();
}
return null;
}
}
package WeGoTogether.wegotogether.entity.FactoryPattern;
public class FactoryPattern {
public static void main(String[] args){
PartFactory partFactory = new PartFactory();
HereWeGo part1 = partFactory.getPart("Web");
// web의 part 메소드 호출
part1.part();
HereWeGo part2 = partFactory.getPart("Flutter");
part2.part();
HereWeGo part3 = partFactory.getPart("Spring");
part3.part();
}
}
추상팩토리에 대해서는 간결하게 설명하고 넘어 가겠다.
추상 팩토리 패턴은 많은 수의 연관된 서브 클래스를 특정 그룹으로 묶어 한번에 교체할 수 있도록 만든 디자인 패턴이다.
내가 만든 코드에 빗대어 보자면 spring은 backend로 web과flutter는 frontend로 묶는다는 뜻이다.
장점
단점
참고자료
elly님
싱글톤(Singleton) 패턴의 정의는 단순하다. 객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미한다.
쉽게 말하자면 메모리 절약을 위해, 인스턴스가 필요할 때 똑같은 인스턴스를 새로 만들지 않고 기존의 인스턴스를 가져와 활용하는 기법을 말한다.
우리가 자주사용하는 전역변수와 비슷하다. 전역변수를 생성해 놓으면 한번 만들어놓고, 가져와 사용하면 효율적이기 때문이다.
싱글톤 패턴 구현
public class Singleton {
// 단 1개만 존재해야 하는 객체의 인스턴스로 static 으로 선언
private static Singleton instance;
// private 생성자로 외부에서 객체 생성을 막아야 한다.
private Singleton() {
}
// 외부에서는 getInstance() 로 instance 를 반환
public static Singleton getInstance() {
// instance 가 null 일 때만 생성
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
먼저 private static으로 Singleton객체의 instance를 선언하고 getInstance()메서드가 처음 실행 될 때만 하나의 instance가 생성되고 그 후에는 이미 생성되어진 instance를 return하는 방식으로 진행이 됩니다.
문제점으로는 멀티스레드에서 사용될시 스레드는 경쟁하게 되는데 그럴때 여러개가 생성 될 가능성이 있다.
이를 해결하기 위해 synchronized라는것을 사용 하게 되는데, 이를 사용하면 동기화로 인해 성능 저하가 발생한다.
참고자료
코딩수첩
죄송한데 블로그 활동 접으셨나여?