1. 싱글톤 패턴 (Singleton Pattern)
이 패턴은 어플리케이션 내에서 특정 클래스의 인스턴스가 하나만 생성되도록 보장합니다. 주로 리소스를 공유해야 할 때 사용됩니다.
public class Singleton {
// 정적 멤버 변수로 유일한 인스턴스를 저장합니다.
private static Singleton instance;
// 생성자를 private으로 선언하여 외부에서 인스턴스화를 막습니다.
private Singleton() {
}
// 인스턴스를 반환하는 정적 메서드를 정의합니다.
public static Singleton getInstance() {
// 인스턴스가 없는 경우에만 인스턴스를 생성합니다.
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 싱글톤 객체의 동작을 정의합니다.
public void doSomething() {
System.out.println("Singleton instance is doing something.");
}
}
public class Main {
public static void main(String[] args) {
// 싱글톤 인스턴스를 가져옵니다.
Singleton singleton = Singleton.getInstance();
// 동일한 인스턴스임을 확인합니다.
Singleton anotherSingleton = Singleton.getInstance();
System.out.println(singleton == anotherSingleton); // 출력: true
// 싱글톤 객체의 동작을 호출합니다.
singleton.doSomething();
}
}
2. 팩토리 패턴 (Factory Pattern)
객체 생성을 하위 클래스로 분리하여 객체를 생성하는 부분을 캡슐화합니다. 이는 코드의 유연성을 높이고 객체 생성에 대한 의존성을 낮출 수 있습니다.
// 제품을 나타내는 인터페이스
interface Product {
void operation();
}
// 구체적인 제품 클래스 1
class ConcreteProduct1 implements Product {
@Override
public void operation() {
System.out.println("ConcreteProduct1 operation");
}
}
// 구체적인 제품 클래스 2
class ConcreteProduct2 implements Product {
@Override
public void operation() {
System.out.println("ConcreteProduct2 operation");
}
}
// 팩토리 인터페이스
interface Factory {
Product createProduct();
}
// 각 제품에 대한 팩토리 클래스
class ConcreteFactory1 implements Factory {
@Override
public Product createProduct() {
return new ConcreteProduct1();
}
}
class ConcreteFactory2 implements Factory {
@Override
public Product createProduct() {
return new ConcreteProduct2();
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
Factory factory1 = new ConcreteFactory1();
Product product1 = factory1.createProduct();
product1.operation();
Factory factory2 = new ConcreteFactory2();
Product product2 = factory2.createProduct();
product2.operation();
}
}
3. 추상 팩토리 패턴 (Abstract Factory Pattern)
관련된 객체들의 집합을 생성하기 위한 인터페이스를 제공하며, 각각의 구상 클래스의 생성을 위임합니다. 이는 객체들 간의 조합이나 의존성을 만들어 내는데 사용됩니다.
// 버튼을 나타내는 인터페이스
interface Button {
void paint();
}
// 윈도우 버튼 클래스
class WinButton implements Button {
@Override
public void paint() {
System.out.println("Windows Button");
}
}
// 맥 버튼 클래스
class MacButton implements Button {
@Override
public void paint() {
System.out.println("Mac Button");
}
}
// 텍스트 필드를 나타내는 인터페이스
interface TextField {
void paint();
}
// 윈도우 텍스트 필드 클래스
class WinTextField implements TextField {
@Override
public void paint() {
System.out.println("Windows TextField");
}
}
// 맥 텍스트 필드 클래스
class MacTextField implements TextField {
@Override
public void paint() {
System.out.println("Mac TextField");
}
}
// 추상 팩토리 인터페이스
interface GUIFactory {
Button createButton();
TextField createTextField();
}
// 윈도우용 팩토리 클래스
class WinFactory implements GUIFactory {
@Override
public Button createButton() {
return new WinButton();
}
@Override
public TextField createTextField() {
return new WinTextField();
}
}
// 맥용 팩토리 클래스
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
GUIFactory factory1 = new WinFactory();
Button button1 = factory1.createButton();
button1.paint();
TextField textField1 = factory1.createTextField();
textField1.paint();
GUIFactory factory2 = new MacFactory();
Button button2 = factory2.createButton();
button2.paint();
TextField textField2 = factory2.createTextField();
textField2.paint();
}
}
4. 스트래티지 패턴 (Strategy Pattern)
알고리즘군을 정의하고, 각각을 캡슐화하며, 이들을 교환하여 사용합니다. 이는 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있도록 합니다.
// 전략을 나타내는 인터페이스
interface Strategy {
void execute();
}
// 구체적인 전략 클래스 1
class ConcreteStrategy1 implements Strategy {
@Override
public void execute() {
System.out.println("Executing strategy 1");
}
}
// 구체적인 전략 클래스 2
class ConcreteStrategy2 implements Strategy {
@Override
public void execute() {
System.out.println("Executing strategy 2");
}
}
// 컨텍스트 클래스
class Context {
private Strategy strategy;
// 전략을 설정하는 메서드
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
// 전략을 실행하는 메서드
public void executeStrategy() {
if (strategy != null) {
strategy.execute();
} else {
System.out.println("No strategy set.");
}
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 컨텍스트 생성
Context context = new Context();
// 첫 번째 전략을 설정하고 실행
Strategy strategy1 = new ConcreteStrategy1();
context.setStrategy(strategy1);
context.executeStrategy();
// 두 번째 전략을 설정하고 실행
Strategy strategy2 = new ConcreteStrategy2();
context.setStrategy(strategy2);
context.executeStrategy();
}
}
5. 옵저버 패턴 (Observer Pattern)
객체 사이에 일대다 의존 관계를 정의합니다. 어떤 객체의 상태가 변하면, 그 객체에 의존하는 다른 객체들에게 자동으로 알림이 가도록 합니다.
import java.util.ArrayList;
import java.util.List;
// 주제를 나타내는 인터페이스
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 옵저버를 나타내는 인터페이스
interface Observer {
void update(String message);
}
// 실제 주제 클래스
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String message;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(message);
}
}
// 상태 변경 메서드
public void setMessage(String message) {
this.message = message;
notifyObservers();
}
}
// 실제 옵저버 클래스
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 주제 생성
ConcreteSubject subject = new ConcreteSubject();
// 옵저버들 생성 및 등록
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
subject.registerObserver(observer1);
subject.registerObserver(observer2);
// 상태 변경 및 옵저버들에게 알림
subject.setMessage("New message!");
}
}
6. 빌더 패턴 (Builder Pattern)
복잡한 객체의 생성 과정을 캡슐화하여, 동일한 생성 과정에서 서로 다른 표현 결과를 만들어 낼 수 있도록 합니다.
// 복잡한 객체를 나타내는 클래스
class Product {
private String part1;
private String part2;
private String part3;
// 생성자를 private로 선언하여 외부에서 직접 객체 생성을 막고, 빌더를 통해 생성하도록 합니다.
private Product(Builder builder) {
this.part1 = builder.part1;
this.part2 = builder.part2;
this.part3 = builder.part3;
}
// 복잡한 객체를 생성하는 빌더 클래스
static class Builder {
private String part1;
private String part2;
private String part3;
// 필수 파라미터를 받는 생성자
public Builder(String part1) {
this.part1 = part1;
}
// 선택적 파라미터를 설정하는 메서드들
public Builder part2(String part2) {
this.part2 = part2;
return this;
}
public Builder part3(String part3) {
this.part3 = part3;
return this;
}
// 복잡한 객체를 생성하는 메서드
public Product build() {
return new Product(this);
}
}
// 객체의 정보를 출력하는 메서드
public void showInfo() {
System.out.println("Part 1: " + part1);
System.out.println("Part 2: " + part2);
System.out.println("Part 3: " + part3);
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 빌더를 사용하여 복잡한 객체를 생성합니다.
Product product = new Product.Builder("Part 1")
.part2("Part 2")
.part3("Part 3")
.build();
// 생성된 객체의 정보를 출력합니다.
product.showInfo();
}
}
7. 프록시 패턴 (Proxy Pattern)
다른 객체에 대한 인터페이스를 제공하여, 해당 객체에 대한 접근을 제어하거나 추가 기능을 제공합니다. 예를 들어, 원격 서비스에 대한 접근을 제어하는 데 사용될 수 있습니다.
// 주제를 나타내는 인터페이스
interface Subject {
void request();
}
// 실제 주제 클래스
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 프록시 클래스
class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
// 실제 주제 객체를 생성하기 전에 필요한 작업을 수행할 수 있습니다.
if (realSubject == null) {
realSubject = new RealSubject();
}
// 실제 주제 객체에 요청을 전달합니다.
realSubject.request();
// 실제 주제 객체에 요청 후에 추가 작업을 수행할 수 있습니다.
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 프록시를 통해 주제 객체에 접근합니다.
Proxy proxy = new Proxy();
proxy.request();
}
}
8. 데코레이터 패턴 (Decorator Pattern)
객체에 추가적인 기능을 동적으로 부여할 수 있도록 합니다. 이는 상속을 통해 기능을 확장하는 것보다 유연하고 강력한 방법을 제공합니다.
// 컴포넌트 인터페이스
interface Component {
void operation();
}
// 구체적인 컴포넌트 클래스
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}
// 데코레이터 클래스
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 구체적인 데코레이터 클래스 1
class ConcreteDecorator1 extends Decorator {
public ConcreteDecorator1(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedBehavior();
}
private void addedBehavior() {
System.out.println("Added behavior from ConcreteDecorator1");
}
}
// 구체적인 데코레이터 클래스 2
class ConcreteDecorator2 extends Decorator {
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedBehavior();
}
private void addedBehavior() {
System.out.println("Added behavior from ConcreteDecorator2");
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 기본 컴포넌트 객체 생성
Component component = new ConcreteComponent();
// 데코레이터를 통해 기본 컴포넌트를 감싸고 추가 기능을 부여
Component decoratedComponent1 = new ConcreteDecorator1(component);
Component decoratedComponent2 = new ConcreteDecorator2(decoratedComponent1);
// 실행
decoratedComponent2.operation();
}
}
9. 팩사드 패턴 (Facade Pattern)
서브 시스템에 있는 인터페이스 집합에 대한 통합된 인터페이스를 제공합니다. 이는 복잡한 시스템을 더 쉽게 사용할 수 있도록 만듭니다.
// 서브시스템의 복잡한 구조를 단순화하는 팩사드 클래스
class CarFacade {
private Engine engine;
private FuelInjector fuelInjector;
private AirConditioner airConditioner;
public CarFacade() {
this.engine = new Engine();
this.fuelInjector = new FuelInjector();
this.airConditioner = new AirConditioner();
}
// 자동차 시동을 켜는 메서드
public void startCar() {
engine.start();
fuelInjector.injectFuel();
airConditioner.turnOn();
System.out.println("Car started!");
}
// 자동차 시동을 끄는 메서드
public void stopCar() {
engine.stop();
airConditioner.turnOff();
System.out.println("Car stopped!");
}
}
// 엔진 클래스 (서브시스템 구성원)
class Engine {
public void start() {
System.out.println("Engine started");
}
public void stop() {
System.out.println("Engine stopped");
}
}
// 연료 주입기 클래스 (서브시스템 구성원)
class FuelInjector {
public void injectFuel() {
System.out.println("Fuel injected");
}
}
// 에어컨 클래스 (서브시스템 구성원)
class AirConditioner {
public void turnOn() {
System.out.println("Air conditioner turned on");
}
public void turnOff() {
System.out.println("Air conditioner turned off");
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 팩사드를 통해 자동차를 조작
CarFacade carFacade = new CarFacade();
carFacade.startCar();
System.out.println("-----");
carFacade.stopCar();
}
}
10. 커맨드 패턴 (Command Pattern)
요청을 객체로 캡슐화하여 매개변수화하고, 메서드 호출, 큐 또는 로깅과 같은 기능을 지원합니다. 이는 요청을 서로 다른 사용자에게 전달하거나 요청의 순서를 지정하거나 취소할 수 있도록 합니다.
// 커맨드 인터페이스
interface Command {
void execute();
}
// 수신자 클래스
class Receiver {
public void action() {
System.out.println("Receiver: Performing action");
}
}
// 구체적인 커맨드 클래스
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
// 인보커 클래스
class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
// 수신자 객체 생성
Receiver receiver = new Receiver();
// 커맨드 객체 생성 및 수신자와 연결
Command command = new ConcreteCommand(receiver);
// 인보커 객체 생성 및 커맨드 설정
Invoker invoker = new Invoker();
invoker.setCommand(command);
// 커맨드 실행
invoker.executeCommand();
}
}
'개발자의 시선 > 개발자' 카테고리의 다른 글
[IT] 레디스(redis) 기본 개념 정리 (1) | 2024.04.26 |
---|---|
[IT] 쿠버네티스(kubernetes) 기본 개념 정리 (0) | 2024.04.22 |
[웹] 카페24 JSP 톰캣 호스팅에 신규 도메인 구매 후 이전 방법 (0) | 2024.01.22 |
[IT] CI/CD 소프트웨어 4종 소개 (0) | 2023.12.21 |
[이클립스] 카멜 표기법 변환 AnyEdit Plugin 소개 (1) | 2023.12.03 |
[IT] 프로그래밍 개발론 간략 정리 소개 (0) | 2023.12.01 |
[JAVA] 이클립스 버그 탐색 도구 SpotBugs 소개 (0) | 2023.11.29 |
[JAVA] spring boot 기본 프로젝트 생성 사이트 소개 (0) | 2023.06.02 |