答えは 1 つではありません。設計とは、優先順位、トレードオフ、妥協点をうまく調整して、状況に応じて適切に機能するものに到達することです。ファンクター、アクセサー、および完全なカプセル化を使用することの相対的なメリットとデメリットについて簡単に説明します。
ファンクタ
ファンクターを使用すると便利で、ボイラープレートの繰り返しを回避できます。これにより、リスト内の各項目に対して実行しているものと、それを実行したときを明確に区別することもできます。for-each ループでは、ほとんどの場合、この 2 つが結合されます。ファンクターが機能しないのは、同じオブジェクトまたは複数のオブジェクトから複数のリストに対して操作を実行する必要がある場合、またはリストのいくつかの要素のみが必要な場合です。ファンクターを使用すると実行順序が制限されます。アイテムは、プロバイダーによって反復される順序で使用する必要があります。ファンクタには制御がありません。これは祝福でもあり、呪いでもあります。
Person、スケジューリング設定、およびスケジューラの例では、スケジューラは可能なスケジュール時間の外部イテレータを提供できます。
schedules = scheduler.schedules(person.getSchedulePreferred())
getSchedulePreferred() は、利用可能なすべてのスケジュールから、特定の人が好むスケジュールを選択する述語を返します。
すべてのスケジュールを反復することは、これを実装する最も効率的な方法ではない場合があります。たとえば、6 月のスケジュールだけが必要な場合、その年の残りのすべてのスケジュールが無駄に繰り返されます。
アクセサー
クラスに固有ではない機能を実装する場合、gtters を介してリストを使用できるようにすることは有益です。たとえば、2 つの注文が与えられた場合、それらに共通する項目を見つけます。これは、リストが外部トラバーサルのゲッターとして提供されている場合は実装が簡単で、リストが既知の順序で提供されている場合 (たとえば、 Order にgetSortedItems()
メソッドがある場合) は非常に簡単です。多くの言語ではリストの可変性を管理するのが複雑です。ミューテーション (C++ の const など) を無効にするか、不変のラッパーでリストをラップする直接サポートがあります。
たとえば、ユーザーはスケジュール設定のリストを公開できます。これは、スケジューラによって直接使用されます。スケジューラーには、プリファレンスがどのように適用されるかについて「スマート」になる機会があります。たとえば、データベースへのクエリを作成して、個人のプリファレンスに基づいて一致するスケジュールを取得できます。
カプセル化
3 番目の選択肢は、外部アクセスが必要かどうかを質問することです。オブジェクトがすべてプロパティであり、動作がないというのは、貧血ドメイン モデルの 1 つの症状です。ただし、このアンチパターンを回避するためだけに動作をドメイン オブジェクトに入れようとしないでください。動作は、そのオブジェクトの責任の自然な部分でなければなりません。
これはここには当てはまらないと思います。担当者、スケジューラ、およびスケジューリングの設定は、明らかに異なる役割を果たし、明確な責任を負っています。別のエンティティからデータを計算しようとするメソッドを 1 つのエンティティに追加すると、不要な密結合になります。
概要
この特定のケースでは、ファンクターを介して「強制的に供給」されるのではなく、スケジューラーがスケジュール設定の使用方法をより詳細に制御できるため、私の好みはゲッターです。