Open bumdream opened 6 years ago
프록시 = 대리자
어떤 작업을 할 때, 구체적으로 인터페이스를 사용하고 실행시킬 클래스에 대한 객체가 들어갈 자리에 대리자 객체를 대신 투입해 작업을 대신 시키는 패턴.
일단 프록시 패턴의 특징은 다음 4가지와 같다
쓰는 이유는 4번째가 핵심이라고 생각하는데, 데이터가 크거나 해서 로딩작업이 느릴 때 등 작업시간이 긴 경우,
일단 완료된 상태까지만 유저에게 제공하거나 그 시간 동안 다른 작업을 하려는 경우에 쓸모 있을 것 같다.
주의할 점: 프록시는 흐름제어만 할 뿐 결과값을 조작하거나 변경시키면 안됩니다.
프록시가 실제 작업 객체를 필드로 가지고 있으면서 해당 함수를 호출한다. 그렇기 때문에 작업 딜레이 동안 프록시는 다른 일을 할 수 있다.
출처: 림키
public interface SubtitleParser {
List<SubtitleObject> parse(String subtitlePath) throws IOException;
}
SubtitleParser parser = ParseFactory.INSTANCE.createParser(subtitlePath);
List<SubtitleObject> subtitleList = parser.parse(subtitlePath);
package SingleTonExample;
public class EagerInitialization {
//private static으로 선언
private static EagerInitialization instance = new EagerInitialization();
//생성자
private EagerInitialization() {}
//인스턴스 리턴
public static EagerInitialization getInstance() {
return instance;
}
}
클래스 인스턴스가 사용되는 시점에 인스턴스를 만드는 패턴
public class LazyInitialization {
private static LazyInitialization instance;
private LazyInitialization () {}
public static LazyInitialization getInstance () {
if ( instance == null )
instance = new LazyInitialization();
return instance;
}
public void print () {
System.out.println("It's print() method in LazyInitialization instance.");
System.out.println("instance hashCode > " + instance.hashCode());
}
}
new LayzaInitializatoin()
은 getInstance()
메소드 안에서 사용되었다.public class ThreadSafeInitalization {
private static ThreadSafeInitalization instance;
private ThreadSafeInitalization () {}
public static synchronized ThreadSafeInitalization getInstance () {
if (instance == null)
instance = new ThreadSafeInitalization();
return instance;
}
public void print () {
System.out.println("It's print() method in ThreadSafeInitalization instance.");
System.out.println("instance hashCode > " + instance.hashCode());
}
}
getInstance()
메소드에 synchronized 를 붙임으로써 저 메소드는 서로 다른 스레드가 동시에 실행할 수 없다.jvm의 클래스로더 메카니즘과 class의 load 시점을 이용한 방식
public class InitializationOnDemandHolderIdiom {
private InitializationOnDemandHolderIdiom () {}
private static class Singleton {
private static final InitializationOnDemandHolderIdiom instance = new InitializationOnDemandHolderIdiom();
}
public static InitializationOnDemandHolderIdiom getInstance () {
System.out.println("create instance");
return Singleton.instance;
}
}
public enum EnumInitialization {
INSTANCE;
static String test = "";
public static EnumInitialization getInstance() {
test = "test";
return INSTANCE;
}
}
전략 패턴에 익명 내부 클래스를 가미한 패턴
하나의 컨텍스트에서만 사용하는 전략일 때, 불필요한 클래스 생성을 방지할 수 있다.
다음은 자주 쓰는 탬플릿 콜백 패턴 형태
Strategy.java (전략 인터페이스 정의)
public interface Strategy { void runStrategy(); }
SoliderWithRefactoring.java (전략을 사용할 컨텍스트 + 내부 익명 클래스 이관 당함)
public class SoliderWithRefactoring {
void runContext(String StrategySound) {
execute(StrategySound).runStrategy();
}
private Strategy execute(final String StrategySound) {
return new Strategy() {
@Override
public void runStrategy() {
System.out.println(StrategySound);
}
};
}
}
Client.java (클라이언트 Solider안에 내부 익명 클래스를 이관했다. -> 코드가 깔끔해짐)
public class Client {
public static void main(String[] args) {
SoliderWithRefactoring rambo = new SoliderWithRefactoring();
rambo.runContext("탕! 탕탕탕!");
rambo.runContext("수류탄 투척~! 쾅!!!");
}
}
Strategy 인터페이스를 통해 OCP와 DIP를 지켰다.
싱글톤 패턴 리뷰
"해당 클래스의 인스턴스가 하나만 만들어지고,
어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴"
출처: http://hjjungdev.tistory.com/4 [우아한 프로그래밍]
Synchronized
(thread safe initialization 읽다가 헷갈려서 다시 찾아봄)
Synchronized 메소드를 사용하는 동안에 다른 스레드에서 해당 메소드를 가진 객체를 사용할 수 없음
출처: 해시코드
public class Volt {
private int volts;
public Volt(int v) {
this.volts = v;
}
public int getVolts() {
return this.volts;
}
public void setVolts(int volts) {
this.volts = volts;
}
}
public class Socket {
public Volt getVolt() {
return new Volt(120);
}
}
public interface SocketAdapter {
public Volt get120Volt();
public Volt get12Volt();
public Volt get3Volt();
}
extends Socket implements SocketAdapter
public class SocketClassAdapterImpl extends Socket implements SocketAdapter {
public Volt get120Volt() {
return getVolt();
}
public Volt get12Volt() {
Volt v = getVolt();
return convertVolt(v, 10);
}
public Volt get3Volt() {
Volt v = getVolt();
return convertVolt(v, 40);
}
public Volt convertVolt(Volt v, int i) {
return new Volt(v.getVolts()/i);
}
}
implements SocketAdapter(Socket 은 내부변수로 가지고 있기)
public class SocketObjectAdapterImpl implements SocketAdapter {
private Socket sock = new Socket();
public Volt get120Volt() {
return sock.getVolt();
}
public Volt get12Volt() {
Volt v = sock.getVolt();
return convertVolt(v, 10);
}
public Volt get3Volt() {
Volt v = sock.getVolt();
return convertVolt(v, 40);
}
private Volt convertVolt(Volt v, int i) {
return new Volt(v.getVolts()/i);
}
}
팩토리에서 객체를 생성해 반환하는 패턴.
Concrete Creator(팩토리)에서 Concrete Product(객체)를 생성, 반환함.
public class ConcreteFactory extends Factory{
@Override
public Product createProduct(String name) {
switch (name) {
case "AAA": return new ProductA();
case "BBB": return new ProductB();
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ConcreteFactory factory = new ConcreteFactory();
List<Product> products = new ArrayList<>();
products.add(factory.createProduct("AAA"));
products.add(factory.createProduct("BBB"));
for(Product product : products){
System.out.println(productA.getName()+"\n");
}
}
}
기본적으로 DIP를 지키는 패턴 (상위와 하위 객체는 구상 클래스에 의존하지 않고, 모두 동일한 추상화에 의존)
장점
자기가 원하는 거 공부 (1개 또는 2개)