ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [자바 디자인 패턴] Flyweight 패턴
    Java/Design Pattern 2020. 5. 12. 00:55

    ■Flyweight 패턴이란?


    영문 그대로 데이터를 표현하는 클래스를 좀 더 가볍게 사용하는 것이 목적인 패턴.


    한번 생성된 클래스를 버리지 않고 모아뒀다가 필요할 때 계속 재사용.


    정적 팩터리 메서드와 비슷한 기법이라고 할 수 있음.




    ■패턴 구현 간단 설명


    데이터 클래스를 관리하는 팩토리 클래스를 준비한다.


    데이터 클래스를 사용하고 싶은 사용자 클래스는 오직 팩토리 클래스를 이용해서


    원하는 데이터 클래스를 얻어온다.


    롤을 가끔 하는데, 롤 캐릭터와 무기를 이용해서 이 패턴을 설명해보겠다.


     사용자 클래스

     Talon.java

     Yasou.java

     Irelia.java

     팩토리 클래스

     WeaponFactory.java

     데이터 클래스

     InfinityEdge.java

     BlackCleaver.java


    맨 위의 사용자 클래스는 오직 가운데의 팩토리 클래스를 이용해서만 


    데이터 클래스를 얻을 수 있다. 아래에 클래스 다이어그램이 있다.




    ■예제 코드


    하나씩 뜯어보겠다!


    1. Champion

    public interface Champion {
    void fight();
    void setWeapon(Weapon weapon);
    }
    public abstract class AbstractCampion implements Champion {
    protected Weapon weapon;

    abstract public void fight();

    public void setWeapon(Weapon weapon) {
    this.weapon = weapon;
    }
    }
    public class Irelia extends AbstractCampion {
    @Override
    public void fight() {
    System.out.println("이렐리아 전투!");
    super.weapon.attack();
    }
    }
    public class Talon extends AbstractCampion {
    @Override
    public void fight() {
    System.out.println("탈론 전투!");
    super.weapon.attack();
    }
    }

    public final class Yasuo extends AbstractCampion {
    @Override
    public void fight() {
    System.out.println("야스오 전투!");
    super.weapon.attack();
    }
    }

    챔피언 클래스들은 사실 Flyweight 패턴과는 관계가 없다.


    이왕 만드는 예제, 제대로 만들어보려고 챔피언 클래스도 구조를 잡아봤다.


    각 final class에서는 fight 메소드만 잘 구현해주면 된다. 


    2. Weapon

    public interface Weapon {
    void attack();
    }
    public class BlackCleaver implements Weapon {
    @Override
    public void attack() {
    System.out.println("칠흑의 양날 도끼 공격!");
    }
    }
    public class InfinityEdge implements Weapon {
    @Override
    public void attack() {
    System.out.println("무한의 대검 공격!");
    }
    }

    각 무기를 정의했다.


    상상의 나래를 펼쳐, 무기는 혹시 상속될 지 몰라 final 키워드를 제거했다.


    3. WeaponFactory

    public class WeaponFactory {
    private static final HashMap<WeaponEnum,Weapon> weaponRoom = new HashMap<>();

    public static Weapon getWeapon(WeaponEnum weaponEnum) {
    Weapon weapon = weaponRoom.get(weaponEnum);

    if (Objects.isNull(weapon)) {
    weapon = weaponEnum.getWeapon();
    System.out.println(weapon.getClass() + " 무기 생성!");
    weaponRoom.put(weaponEnum, weapon);
    }

    return weapon;
    }
    }

    제일 중요한 놈이 나왔다.


    getWeapon 메소드 안에선 이미 생성된 적이 있는 무기일 경우 전에 생성됐던 무기를 


    다시 꺼내온다! 또 getWeapon 메소드 안에서 if를 안쓰기 위해서 Enum을 정의했다.

    public enum WeaponEnum {
    INFINITY_EDGE(InfinityEdge::new),
    BLACK_CLEAVER(BlackCleaver::new);

    private Supplier<Weapon> supplier;

    WeaponEnum(Supplier<Weapon> supplier) {
    this.supplier = supplier;
    }

    public Weapon getWeapon() {
    return this.supplier.get();
    }
    }

    이 Enum을 통해 불필요한 if를 제거해서 코드 가독성을 높였다.


    4. 결과(로그)

    public class Main {
    public static void main(String[] args) {
    Champion irelia = new Irelia();
    irelia.setWeapon(WeaponFactory.getWeapon(WeaponEnum.BLACK_CLEAVER));
    irelia.fight();

    Champion yasuo = new Yasuo();
    yasuo.setWeapon(WeaponFactory.getWeapon(WeaponEnum.INFINITY_EDGE));
    yasuo.fight();

    Champion talon = new Talon();
    talon.setWeapon(WeaponFactory.getWeapon(WeaponEnum.BLACK_CLEAVER));
    talon.fight();
    }
    }

    이렐리아, 야스오(과학), 탈론을 정의한 후 


    칠흑의 양날 도끼, 무한의 대검, 칠흑의 양날 도끼를 각각의 손에 쥐어줬다.


    칠흑의 양날 도끼가 두번 언급이 되는데, 탈론에게 주어지는 칠흑의 양날 도끼는 


    이렐리아에게 주어진 도끼가 다시한번 사용되어야 한다!!


    위 메인 메소드를 실행시켜보면

    class com.uad2.application.test.weapon.BlackCleaver 무기 생성!
    이렐리아 전투!
    칠흑의 양날 도끼 공격!

    class com.uad2.application.test.weapon.InfinityEdge 무기 생성!
    야스오 전투!
    무한의 대검 공격!

    탈론 전투!
    칠흑의 양날 도끼 공격!

    이렇게 나온다. 예상대로 두번째 칠흑의 양날 도끼는 새로 생성되지 않는다!!


    예제 끝~


    'Java > Design Pattern' 카테고리의 다른 글

    [자바 디자인 패턴] 싱글톤 패턴(Singleton Pattern)  (0) 2020.06.01

    댓글

Designed by Tistory.