4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

디자인 패턴 with 자바 - 낭비를 없애기(Flyweight, Proxy)

르무엘 2023. 3. 9. 01:54

박은종의 객체지향 설계를 위한 디자인패턴 with 자바

 

낭비를 없애기(Flyweight, Proxy)

 

 

  • 공유를 통하여 인스턴스의 수를 절약한다.
  • 인스턴스마다의 특성이 거의 없는 객체에 사용하는 것이 효율적이다.
  • 부가적인 정보가 많은 경우는 비효율적일 수 있다.

 

package com.backend.bakckend.designpattern.waste;


import java.util.Hashtable;

class BigChar{
    private char charname;
    private String fontdata;
    public BigChar(char charname) {
        this.charname = charname;
        try {
            this.fontdata = readFontData(charname);
        } catch (Exception e) {
            this.fontdata = charname + "?";
        }
    }
    private String readFontData(char charname) {
        return "fontdata";
    }
    public void print() {
        System.out.println(fontdata);
    }
}

class BigCharFactory{

    private Hashtable<String,BigChar> pool = new Hashtable<String,BigChar>();
    private static BigCharFactory singleton = new BigCharFactory();
    private BigCharFactory() {
    }

    public static BigCharFactory getInstance() {
        return singleton;
    }

    public synchronized BigChar getBigChar(char charname) {
        BigChar bc = (BigChar) pool.get("" + charname);
        if(bc == null) {
            bc = new BigChar(charname);
            pool.put("" + charname, bc);
        }
        return bc;
    }

}


class BigString{

    private BigChar[] bigchars;
    public BigString(String string) {
        bigchars = new BigChar[string.length()];
        BigCharFactory factory = BigCharFactory.getInstance();
        for (int i = 0; i < bigchars.length; i++) {
            bigchars[i] = factory.getBigChar(string.charAt(i));
        }
    }

    public void print() {
        for (int i = 0; i < bigchars.length; i++) {
            bigchars[i].print();
        }
    }

}

public class Flyweight {

    public static void main(String[] args) {
        BigString bs = new BigString("1234567890");
        bs.print();
    }
}

 

Proxy Pattern

객체에 대한 접근을 제어하기 위해 대리자를 둔다

 

  • 어떤 객체가 생성에 초기화 비용이 많이 들거나 복잡한 경우 간단한 처리는 대리자를 통해 하게한다.
  • 실제적으로 비용이 많이 들어가는 처리일 때 객체를 만들도록 한다.

 

프록시 패턴은 객체에 접근하는데 보호, 가상등의 역할을 한다.

package com.backend.bakckend.designpattern.waste;


interface Printable {
    void setPrinterName(String name);
    String getPrinterName();
    void print(String string);
}

class PrinterProxy implements Printable {
    private String name;
    private Printer real;

    public PrinterProxy() {
    }

    public PrinterProxy(String name) {
        this.name = name;
    }

    @Override
    public synchronized void setPrinterName(String name) {
        if (real != null) {
            real.setPrinterName(name);
        }
        this.name = name;
    }

    @Override
    public String getPrinterName() {
        return name;
    }

    @Override
    public void print(String string) {
        realize();
        real.print(string);
    }

    private synchronized void realize() {
        if (real == null) {
            real = new Printer(name);
        }
    }
}

class Printer implements Printable{
    private String name;
    public Printer() {
        heavyJob("Printer의 인스턴스를 생성 중");
    }
    public Printer(String name) {
        this.name = name;
        heavyJob("Printer의 인스턴스(" + name + ")을 생성 중");
    }
    public void setPrinterName(String name) {
        this.name = name;
    }
    public String getPrinterName() {
        return name;
    }
    public void print(String string) {
        System.out.println("=== " + name + " ===");
        System.out.println(string);
    }
    private void heavyJob(String msg) {
        System.out.print(msg);
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.print(".");
        }
        System.out.println("완료.");
    }

}


public class Proxy {
    public static void main(String[] args) {
        Printable p = new PrinterProxy("Alice");
        System.out.println("이름은 현재 " + p.getPrinterName() + "입니다.");
        p.setPrinterName("Bob");
        System.out.println("이름은 현재 " + p.getPrinterName() + "입니다.");
        p.print("Hello, world.");
    }
}
LIST