構造設計モード(3)-軽量レベルモード、エージェントモード


軽量モード


オブジェクトを軽くすることでメモリの使用を減らすモード
  • は、頻繁に変化する属性と不変の属性とを分離して再使用することができ、各属性の使用を低減することができる.
  • public class Character {
    
        private char value;
    
        private String color;
    
        private String fontFamily;
    
        private int fontSize;
    
        public Character(char value, String color, String fontFamily, int fontSize) {
            this.value = value;
            this.color = color;
            this.fontFamily = fontFamily;
            this.fontSize = fontSize;
        }
    }
    
    
     public static void main(String[] args) {
            Character c1 = new Character('h', "white", "Nanum", 12);
            Character c2 = new Character('e', "white", "Nanum", 12);
            Character c3 = new Character('l', "white", "Nanum", 12);
            Character c4 = new Character('l', "white", "Nanum", 12);
            Character c5 = new Character('o', "white", "Nanum", 12);
        }
    
    フォントシリーズやフォントサイズの色などが重なり、メモリがたくさん占められています.
    
    public final class Font {
    
        final String family;
        final int size;
    
        /**
         *  플라이웨이트에해당하는 인스턴스는 불변해야한다.
         *     다른여러 객체에서 공유하는 객체이기때문이다.
         *     클래스에 final 필드값에 final을 붙였다.    
         */
    
        public Font(String family, int size) {
            this.family = family;
            this.size = size;
        }
    
        public String getFamily() {
            return family;
        }
    
        public int getSize() {
            return size;
        }
    }
    ヘビー級のインスタンスは変わらないはずです.
    public class Character {
    
        private char value;
    
        private String color;
    
        private Font font;
    
        public Character(char value, String color, Font font) {
            this.value = value;
            this.color = color;
            this.font = font;
        }
    }
    
    
    public class FontFactory {
    
        private Map<String, Font> cache = new HashMap<>();
    
        public Font getFont(String font) {
            if (cache.containsKey(font)) {
                return cache.get(font);
            } else {
                String[] split = font.split(":");
                Font newFont = new Font(split[0], Integer.parseInt(split[1]));
                cache.put(font, newFont);
                return newFont;
            }
        }
    }
    
    
       public static void main(String[] args) {
            FontFactory fontFactory = new FontFactory();
            Character c1 = new Character('h', "white", fontFactory.getFont("nanum:12"));
            Character c2 = new Character('e', "white", fontFactory.getFont("nanum:12"));
            Character c3 = new Character('l', "white", fontFactory.getFont("nanum:12"));
        }
    


    軽量モード
    長所
  • アプリケーションで使用されるメモリを削減します.
  • 短所
  • コードの複雑さが増加しました.
  • 数値や文字列を比較するときは=を書かないでください.

    プロキシモード


    特定のオブジェクトへのアクセスまたは追加機能を制御するモード.
  • 初期化遅延、アクセス制御、ログ記録、キャッシュなど.
  • プロキシ=インタフェースにフィールド値があります.
    を参照してください.
    public class GameService {
    
        public void startGame() {
            System.out.println("이 자리에 오신 여러분을 진심으로 환영합니다.");
        }
        // 코드의 실행시간을 확인하고싶은데 코드는 변경할수없다.
    
    }
        public static void main(String[] args) throws InterruptedException {
            GameService gameService = new GameService();
            gameService.startGame();
        }
        // 코드를 추가하면 시간을 잴수있겠지만, 코드를 유지하면서 시행하고싶다.
    
    public class GameServiceProxy extends GameService {
    
        @Override
        public void startGame() {
            long before = System.currentTimeMillis();
            super.startGame();
            System.out.println(System.currentTimeMillis() - before);
        }
    }
    
       public static void main(String[] args) {
            GameService gameService = new GameServiceProxy();
            gameService.startGame();
        }
    
    クラスを作成し、継承で解決
    GameServiceを修復できない場合は、これが解決策になる可能性があります.
    だが君が手を出せば
    
    public interface GameService {
    
        void startGame();
    
    }
    
    public class DefaultGameService implements GameService{
    
        @Override
        public void startGame() {
            System.out.println("이자리에 오신걸 환영합니다");
        }
    }
    GameServiceをインタフェースとして使用します.
    public class GameServiceProxy implements GameService {
    
        private GameService gameService;
    
      //    public GameServiceProxy(DefaultGameService defaultGameService) {
    //        this.gameService = gameService;
    //    }
    
        @Override
        public void startGame() {
            long before = System.currentTimeMillis();
              if (gameService == null) {
                this.gameService = new DefaultGameService();
            }
            gameService.startGame();
            System.out.println(System.currentTimeMillis() - before);
    
        }
    }
      public static void main(String[] args) {
           // GameService gameService = new GameServiceProxy(new DefaultGameService());
            //gameService.startGame();
           
              GameService gameService = new GameServiceProxy();
            gameService.startGame();
        }
    クライアントはDefaultGameServiceを使用する必要がありますが、GameServiceProxyで使用します.

    エージェント・モードの利点

  • は、既存のコードを変更することなく、新しい機能を追加することができる.
  • は、既存のコードが行う作業のみを維持します.
  • 機能プールランプの追加と初期化が可能で、広く使用できます.
  • 短所

  • コードの複雑さが増加しました.
  • 使用例

      public static void main(String[] args) {
            ProxyInJava proxyInJava = new ProxyInJava();
            proxyInJava.dynamicProxy();
        }
    
        private void dynamicProxy() {
            GameService gameServiceProxy = getGameServiceProxy(new DefaultGameService());
            gameServiceProxy.startGame();
        }
    
        private GameService getGameServiceProxy(GameService target) {
            return  (GameService) Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    new Class[]{GameService.class}, (proxy, method, args) -> {
                        System.out.println("O");
                        method.invoke(target, args);
                        System.out.println("ㅁ");
                        return null;
                    });
        }
    実行時に動的に作成されたエージェント
    これらの機能を複数の方法に適用する必要がある場合、
    似たようなコードはたくさんありますが、動的に実行時に生成することができ、より効率的に使用できます.
    スプリング上のAOP
    異なる場所に分散した概念を集中的に処理する概念.
    @Service
    public class GameService {
    
        public void startGame() {
            System.out.println("이 자리에 오신 여러분을 진심으로 환영합니다.");
        }
    
    }
    
    @Aspect
    @Component
    public class PerfAspect {
    
        @Around("bean(gameService)")
        public void timestamp(ProceedingJoinPoint point) throws Throwable {
            long before = System.currentTimeMillis();
            point.proceed();
            System.out.println(System.currentTimeMillis() - before);
        }
    }
    
    評価は、スプリングによって管理されるbeanにのみ適用できます.
    @Componentロビンとして登録されています.
    スプリング起動時にbeanを動的に作成して登録します.
    プロシビンを注入して使用します.
    関連項目:https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4#