load メソッドがある場所に、VegetableManager (または何か) クラスを配置することもできますが、これは実際にはコードの繰り返しが少ないことを意味するのでしょうか? 次に、各画面で、VegetableManager のオブジェクトを作成し、とにかくその load メソッドを呼び出す必要があります。
これを行うポイントは、効率 (つまりパフォーマンス) ではありません。ポイントは、そのデータのロードの詳細を単一の分離されたオブジェクトにカプセル化することです。たとえば、サイトが非常に大きくなり、スケーラビリティとパフォーマンスのためにデータ ストレージをデータベースに移動することにしたとします。説明した既存のコードでは、各ユーザー コントロールまたはページを調べて、load メソッドのロジックを変更する必要があります。せいぜいこれは苦痛であり、最悪の場合、一部を見逃したり、誤ってコピーアンドペーストしたりします. ロジックが専用のオブジェクトにカプセル化されている場合、その唯一の責任はどこかからデータをロードする方法を知ることであり、変更を行う必要があるのは 1 回だけです。
ユーザーコントロールの分離コード:
protected void Page_Load(object sender, EventArgs e) {
var veggieManager = new VegetableManager();
VeggieListControl.DataSource = veggieManager.GetAll();
VeggieListControl.DataBind();
}
野菜マネージャー.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
public ReadOnlyCollection<Vegetable> GetAll() {
if (_veggies == null) {
lock(_veggieLock) { //synchronize access to shared data
if (_veggies == null) { // double-checked lock
// logic to load the data into _veggies
}
}
}
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
GetAll(); // call this to ensure that the data is loaded into _veggies
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
_veggies
isであるためstatic
、複数の呼び出し元が をインスタンス化するという事実にもかかわらず、メモリには野菜のコレクションが 1 つしかありませんVegetableManager
。ただし、静的であるため、マルチスレッド アプリケーション (Web サイトなど) を使用している場合は、すべてのスレッドでそのフィールドへのアクセスを同期する必要があります (したがってlock
s)。
これは、優れたオブジェクト指向という点では氷山の一角です。UncleBob の SOLID の原則とDomain-Driven Design (無料の電子書籍)を熟読することをお勧めします。
はい、何かを繰り返していますが、繰り返しているのはメソッド呼び出しだけであり、繰り返しても問題ありません。DRY は、「論理」コード、つまり意思決定とアルゴリズムの重複を軽減することを意味します。単純なメソッド呼び出しはこれに該当しません。ただし、必要に応じて、ロジックを基本クラスに統合して、これを行うことで、ユーザーコントロールが野菜マネージャーについて知る必要がないように効果的に分離できますが、これはオブジェクト指向のやり過ぎ、または OOO だと思います:-)
public abstract class FoodUserControl : UserControl {
protected List<Vegetable> GetVeggies() {
return new VegetableManager().GetAll();
}
}
次に、実際のコントロールは、UserControl からではなく、これから派生します。
アップデート
イーガーローディングのVegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
static VegetableManager() {
// logic to load veggies from file
}
public ReadOnlyCollection<Vegetable> GetAll() {
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
この熱心な読み込みバージョンでは、コンストラクターの読み込みコードの周りで二重チェックのロックを行う必要がないことに注意してください。また、このコードはフィールドを初期化するため、ロード コードがstatic
コンストラクター内にあることに注意してstatic
ください (そうしないと、すべての構築でファイルからデータを同じ共有static
フィールドに再ロードすることになります)。野菜は熱心に読み込まれるため、GetAll または Add で読み込む必要はありません。