[Java]関数式プログラミング設計モード

55179 ワード

Design Pattern

  • は、繰り返されるプログラミング問題の解決策をモデル化した
  • である.
  • モードを熟知している場合、同様の問題が発生すると、マイルストーン
  • になります.
  • タイプ
  • アレイの作成
  • オブジェクトを作成するモード
  • 構造モード
  • はモード
  • を継承し、クラス/オブジェクトを組み合わせてより高い構造を持つ
  • 動作モード
  • モード
  • 必要な動作を複数のオブジェクトに割り当てることで、オブジェクト間の結合を低減
  • 設計モードの実施には、大量のインタフェース/クラス/方法が必要である.
  • 関数式プログラミングはいくつかのモード
  • を簡略化した.

    ビルダーモード

  • オブジェクトを作成する論理を表現から分離し、
  • オブジェクト
  • の作成プロセスまたはフィールドを定義しすぎる場合は、コンストラクション関数が複雑になるときに便利です.
  • ex) setter
  • setterを削除して、オブジェクトが変更(可変)されないことを確認します.
    作成者のパラメータは、
  • ではなく増加します.
  • ジェネレータを呼び出すときの順序は複雑である
  • .
  • ジェネレータを使用して作成
  • ジェネレータも最終的に複雑になる
  • .
  • 関数式プログラミング改善
  • 改良構造(Functional)

  • public static class Builder {
       private int id;
       private String name;
       
       private Builder() {
       }
       
       public Builder with(Consumer<Builder> consumer) {
           consumer.accept(this);
           return this;
       }
       
       public Object build() {
       	return new Object(this);
       }
    }
  • public class BuilderExample {
    	public static void main(String[] args) {
           Object obj = Object.builder()
               .with(builder -> {
                   builder.id = 1;
                   builder.name = "functional builder";
               }).build();
       }
    }
  • 装飾図案

  • 構造様式の1つである
  • の用途により、引き続き対象に機能(装飾)
  • を追加することができる.
  • 既存構造
    「価格設定」を実装するオブジェクトを入力し、状況に応じて適用可能な
  • メソッドを選択します.メソッドを再定義する必要はありません.
  • では、各機能に1つのメインプロセッサがあるため、効率が低下する
  • メインプロセッサを作成することなく、関数によって定義され、すぐに有効になります.
  • public class Price {
    	private final String price
       
       public Price(String price) {
       	this.price = price;
       }
       
       public String getPrice() {
       	return price;
       }
    }
  • // Functional Interface (메소드 하나)
    public interface PriceProcessor {
    	Price process(Price price);
       
       // 다음에 실행될 프로세서를 받아와서 기존 프로세서를 처리하고 next 프로세서를 처리해서 새로운 Price를 만들어줌
       default PriceProcessor andThen(PriceProcessor next) {
       	return price -> next.process(process(price));
       }
    }
  • 戦略モデル

  • 代表的な行動パターン
  • 実行時に選択できるポリシー(アルゴリズム):
  • 戦略パッケージで、
  • を簡単に交換できます.

    定義済み

  • public interface Provider {
    	String getName(Object object);
    }
    
    public class Sender {
    	private Provider provider;
       
       public Sender setProvider(Provider provider) {
       	this.provider = provider;
           return this;
       }
       
       public void sendName(Object object) {
       	String name = Provider.getName(object);
       }
    }
    
    public class ProviderImpl1 {
    	@Override
    	public String getName(Object object) {
       	return "imple type1 " + object.getName();
       };
    }
    
    public class ProviderImpl2 {
    	@Override
    	public String getName(Object object) {
       	return "imple type2 " + object.getName();
       };
    }
  • 戦略的選択の比較

  • public class MainClass {
    	public static void main(String[] args) {
       	Object obj1 = Object.builder("name1").build();
           Object obj2 = Object.builder("name2").build();
           Object obj3 = Object.builder("name3").build();
           
           List<Object> objs = Arrays.asList(obj1, obj2, obj3);
           
           Sender sender = new Sender();
           Provider provider1 = new ProviderImpl1();
           Provider provider2 = new ProviderImpl2();
           
           // 전략 선택 1
           sender.setProvider(provider1);
           objs.stream()
           	.forEach(sender::sendName);
           
           // 전략 선택 2
           sender.setProvider(provider2);
           objs.stream()
           	.forEach(sender::sendName);
               
           // 함수형 프로그래밍 개선 (바로 바로 생성해 사용 가능)
           sender.setProvider(object -> "functional " + object.getName()).stream()
           	.forEach(sender::sendName);
       };
    }
  • テンプレートメソッドアレイ

  • は行動パターン
  • を表す.
  • 親クラスはアルゴリズムスケルトンのみを定義し、アルゴリズムの各ステップはサブクラスに割り当てられたモードを定義します.
  • の新しいクラス
  • の作成を続行する必要があります.
  • アルゴリズムの構造は、詳細レベル
  • を柔軟に変更することができる.

    既存の構造

  • public abstract class AbstractService {
        protected abstract boolean validateObject(Object object);
        
        protected abstract void writeToDB(Object object);
        
        public void createObject(Object object) {
            if(validateObject(object)) {
                writeToDB(object);
            } else {
                System.out.println("Cannot create");
            }
        }
    }
    
    public class Service extends AbstractService {
        @Override
        protected abstract boolean validateObject(Object object) {
            return object.getName() != null && user.getFields().isPresent();
        }
        
        @Override
        protected abstract void writeToDB(Object object) {
            System.out.println("write " + object.getName() + " to DB");
        }
    }
    
    // 내부 서비스
    public class InternalService extends AbstractService {
        @Override
        protected abstract boolean validateObject(Object object) {
            return true;
        }
        
        @Override
        protected abstract void writeToDB(Object object) {
            System.out.println("write " + object.getName() + " to internal DB");
        }
    }
    
    public class MainClass {
        public static void main(String[] args) {
            Object object = Object.builder("name")
                .with(builder -> {
                    builder.fields = "fields";
                }).build();
        }
        
        Service service = new Service();
        InternalService internalService = new InternalService();
        
        service.createUser(object);
        internalService.createUser(object);
    }
  • 改良構造(Functional)

  • public class FunctionalService extends AbstractService {
         private final Predicate<Object> validateObject;
         private final Consumer<Object> writeToDB;
         
         public FunctionalService(Predicate<Object> validateObject, Consumer<Object> writeToDB) {
             this.validateObject = validateObject;
             this.writeToDB = writeToDB;
         }
         
         public void createObject(Object object) {
             if(validateObject.test(object)) {
                 writeToDB.accept(object);
             } else {
                 System.out.println("Cannot create");
             }
         }
     }
     
     public class MainClass {
         public static void main(String[] args) {
             Object object = Object.builder("name")
                 .with(builder -> {
                     builder.fields = "fields";
                 }).build();
         }
         
         FunctionalService fService = new FunctionalService(
             object -> {
                 return object.getName().equal("functional");
             },
             object -> {
                 System.out.println("functional writeToDB " + object.getName());
             }
         )
         fService.createObject(object);
     }
  • 責任チェーンモード

  • 動作モード
  • 処理対象があれば、
  • コマンドおよびコマンドをそれぞれ処理することができる.
    チェーン
  • 処理対象
  • チェーンから個々の処理を開始
  • 、できれば
  • に処理して渡す.
  • 不可能なら
  • をスキップ
  • チェーンの末尾で
  • を終了する.
  • は、処理対象を追加することにより、簡単な処理能力
  • を追加することができる.
  • リンクリストは分かりやすい
  • 定義#テイギ#

  • public Class OrderProcessStep {
        private final Consumer<Order> processOrder;
        private OrderProcessStep next;
        
        public OrderProcessStep(Consumer<Order> processOrder) {
            this.processOrder = processOrder;
        }
        
        public OrderProcessStep setNext(OrderProcessStep next) {
            if (this.next == null) {
                this.next = next;
            } else {
                this.next.setNext(next);
            }
            return this;
        }
        
        public void process(Order order) {
            processOrder.accept(order);
            Optional.ofNullable(next)
                .ifPresent(nextStep -> nextStep.process(order));
        }
    }
  • 各ステップの実装

  • public class MainClass {
        public static void main(String[] args) {
            OrderProcessStep initializeStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.CREATED) {
                    logger.info("Start processing order " + order.getId());
                    order.setStatus(OrderStatus.IN_PROGRESS);
                }
            });
            
            OrderProcessStep setOrderAmountStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.IN_PROGRESS) {
                    logger.info("Setting amount of order " + order.getId());
                    order.setAmount(
                        order.getOrderLines().stream()
                        .map(OrderLine::getAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                    );
                }
            }
            
            OrderProcessStep verifyOrderStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.IN_PROGRESS) {
                    logger.info("Verifying order " + order.getId());
                    if(order.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                        order.setStatus(OrderStatus.ERROR);
                    }
                }
            }
            
            OrderProcessStep paymentStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.IN_PROGRESS) {
                    logger.info("payment of order " + order.getId());
                    order.setStatus(OrderStatus.PROCESSED);
                }
            }
            
            OrderProcessStep handleErrorStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.ERROR) {
                    logger.info("Error in order " + order.getId());
                }
            }
            
            OrderProcessStep completeOrderStep = new OrderProcessStep(order -> {
                if(order.getStatus() == OrderStatus.PROCESSED) {
                    logger.info("finished processing order " + order.getId());
                }
            }
            
            // 체이닝
            OrderProcessStep chainedOrderProcessSteps = initializeStep
                .setNext(setOrderAmountStep)
                .setNext(verifyOrderStep)
                .setNext(paymentStep)
                .setNext(handleErrorStep)
                .setNext(completeOrderStep);
                
            // 체인 실행
            chainedOrderProcessSteps.process(order);
        }
    }