객체 생성 과정을 유연하게 만들어 코드의 강한 결합을 방지
단점: 멀티스레드가 경쟁 상태에 돌입할 경우 여러 싱글톤 객체가 생성
public class Singleton {
private **static** Singleton uniqueInstance;
**private** Singleton() {}
public static Singleton getInstance() {
**if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}**
return uniqueInstance;
}
}
단점: 사용하기 전 미리 초기화되어 서 있는 전역 변수에 대한 오버헤드
public class Singleton {
private **static** Singleton uniqueInstance = new Singleton();
**private** Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
단점: synchronized로 인한 성능 악화
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
// Synchronized to prevent thread interference
public static **synchronized** Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
public class Singleton {
private **volatile** static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
**if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}**
return uniqueInstance;
}
}
public **abstract** class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected **abstract** Pizza createPizza(String type);
}
public class DependentPizzaStore {
public Pizza createPizza(String style, String type) {
Pizza pizza = null;
if (style.equals("NY")) {
if (type.equals("cheese")) {
pizza = new NYStyleCheesePizza();
} else if (type.equals("veggie")) {
pizza = new NYStyleVeggiePizza();
}
} else if (style.equals("Chicago")) {
if (type.equals("cheese")) {
pizza = new ChicagoStyleCheesePizza();
} else if (type.equals("veggie")) {
pizza = new ChicagoStyleVeggiePizza();
}
} else {
System.out.println("Error: invalid type of pizza");
return null;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
클래스와 객체를 조합하여 더 큰 구조를 형성하며, 다양한 구조를 통해 클래스와 객체의 관계를 강화
```java
// Adaptee : 클라이언트에서 사용하고 싶은 기존의 서비스 (하지만 호환이 안되서 바로 사용 불가능)
class Adaptee {
void specificRequest() {
System.out.println("기존 서비스 기능 호출 + ");
}
}
// Client Interface : 클라이언트가 접근해서 사용할 고수준의 어댑터 모듈
interface Target {
void request();
}
// Adapter : Adaptee 서비스를 클라이언트에서 사용하게 할 수 있도록 호환 처리 해주는 어댑터
class Adapter implements Target {
Adaptee adaptee; // Composition
// // 어댑터가 인스턴스화되면 호환시킬 기존 서비스를 설정
Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
// 어댑터의 메소드가 호출되면, 부모 클래스 Adaptee의 메소드를 호출
public void request() {
adaptee.specificRequest(); // Delegation
}
}
```
```java
// Adaptee : 클라이언트에서 사용하고 싶은 기존의 서비스 (하지만 호환이 안되서 바로 사용 불가능)
class Adaptee {
void specificRequest() {
System.out.println("기존 서비스 기능 호출 + ");
}
}
// Client Interface : 클라이언트가 접근해서 사용할 고수준의 어댑터 모듈
interface Target {
void request();
}
// Adapter : Adaptee 서비스를 클라이언트에서 사용하게 할 수 있도록 호환 처리 해주는 어댑터
class Adapter extends Adaptee implements Target {
// 어댑터의 메소드가 호출되면, 부모 클래스 Adaptee의 메소드를 호출
public void request(int data) {
specificRequest(data);
}
}
```
Client : 클라이언트는 Component를 참조하여 단일 / 복합 객체를 하나의 객체로서 다룬다.
Component : Leaf와 Composite 를 묶는 공통적인 상위 인터페이스
Composite : 복합 객체로서, Leaf 역할이나 Composite 역할을 넣어 관리하는 역할을 한다.
Leaf: 단일 객체로서, 단순하게 내용물을 표시하는 역할을 한다.
자식 요소들을 관리하는 add()
, remove()
, getChild()
와 같은 메서드는 어디에 선언해야 할까?
Transparency(투명성)
Safety(안전성)
객체 간 통신과 책임 분배에 초점을 맞추며, 복잡한 흐름 제어를 간소화하고, 객체 간의 상호작용을 효율화
public class WeatherData implements Subject {
private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
// Other WeatherData methods (e.g., getTemperature, getHumidity, getPressure)
}
public class CurrentConditionDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
@Override
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
[Design Pattern] Command Pattern(커맨드 패턴)
public interface Command {
public void execute() throw Exception;
}
public class ActiveObjectEngine {
LinkedList<Command> itsCommands = new LinkedList<>();
public void addCommand(Command c) {
itsCommands.add(c);
}
public void run() {
while(!itsCommands.isEmpty()) {
Command c = itsCommands.getFirst();
itsCommands.removeFirst();
c.execute();
}
}
}
public class SleepCommand implements Command {
private Command wakeUpCommand = null;
private ActiveObjectEngine engine= null;
private long sleepTime = 0;
private long startTime = 0;
private boolean started = false;
public SleepCommand(long st, ActiveObjectEngine e, Command wakeUp) {
this.sleepTime = st;
this.engine = e;
this.wakeUpCommand = wakeUp;
}
public void execute() throws Exception {
long currentTime = System.currentTimeMillis();
if (!started) {
started = true;
startTime = currentTime;
engine.addCommand(this);
} else if ((currentTime - startTime) < sleepTime) {
engine.addCommand(this);
} else {
engine.addCommand(wakeUpCommand);
}
}
}
public class DelayedTyper implements Command {
private long itsDelay;
private char itsChar;
private static ActiveObjectEngine engine = new ActiveObjectEngine();
private static boolean stop = false;
public static void main(String[] args) {
engine.addCommand(new DelayedTyper(100, '1'));
engine.addCommand(new DelayedTyper(300, '3'));
engine.addCommand(new DelayedTyper(500, '5'));
engine.addCommand(new DelayedTyper(700, '7'));
Command stopCommand = new Command() {
public void execute() {
stop = true;
}
}
engine.addCommand(new SleepCommand(20000, engine, stopCommand));
engine.run();
}
public DelayedTyper(long delay, char c) {
itsDelay = delay;
itsChar = c;
}
public void execute() throw Exception {
System.out.print(itsChar);
if(!stop) delayAndRepeat();
}
public void delayAndRepeat() throws Exception {
engine.addCommand(new SleepCommand(itsDelay, engine, this));
}
}