Я пытаюсь реализовать шаблон наблюдателя на C#, хотите знать, правильно ли я это сделал?
Я очень новичок в Observer Pattern, думаю, что в некоторых случаях это очень полезно, поэтому я написал простой проект, я не уверен, что сделал это правильно или нет, любые предложения будут оценены.
class Program
{
public delegate void ProductAddedEventHandler(Object sender, ProductAddedEventArgs e);
public class Products
{
private double subtotal;
public event ProductAddedEventHandler ProductAdded;
public void Add(Product product)
{
ProductModels model = new ProductModels();
IEnumerable<Product> products = model.Products();
IEnumerable<Product> new_Collection = products.Concat(new List<Product>() { product });
Calculate calculate = new Calculate();
this.subtotal = calculate.create(new_Collection);
if (ProductAdded != null)
{
ProductAddedEventArgs e = new ProductAddedEventArgs(subtotal);
ProductAdded(this, e);
}
Console.WriteLine("Subtotal Amount: {0}", subtotal);
}
}
/// <summary>
/// Calculate the Subtotal
/// </summary>
public class Calculate
{
public double create(IEnumerable<Product> products)
{
double result = 0;
foreach (Product p in products)
{
result += p.Price;
}
return result;
}
}
public class ProductAddedEventArgs : EventArgs
{
public readonly double SubTotal;
public ProductAddedEventArgs(double subtotal) => SubTotal = subtotal;
}
public class Shipping
{
const double Shipping_Rate = 0.05;
public void create(Object sender, ProductAddedEventArgs e)
{
Console.WriteLine("Shipping Amount: {0}", e.SubTotal * Shipping_Rate);
}
}
public class Discount
{
const double Discount_Rate = 0.2;
public void create(Object sender, ProductAddedEventArgs e)
{
Console.WriteLine("Discount Amount: {0}", e.SubTotal * Discount_Rate);
}
}
public class Tax
{
const double Tax_Rate = 0.07;
public void create(Object sender, ProductAddedEventArgs e)
{
Console.WriteLine("Tax Amount: {0}", e.SubTotal * Tax_Rate);
}
}
static void Main(string[] args)
{
Products products = new Products();
Shipping shipping = new Shipping();
Discount discount = new Discount();
Tax tax = new Tax();
products.ProductAdded += shipping.create;
products.ProductAdded += discount.create;
products.ProductAdded += tax.create;
products.Add(new Product()
{
Id = 50,
Name = "Watermelon",
Price = 9.21
});
}
}
Кстати, как получить общую сумму?
1 ответ
Хотя этот вопрос принадлежит https://codereview.stackexchange.com/ но я постараюсь написать краткий ответ.
Определение шаблона Observer из DoFactory(GOF),
Шаблон Observer определяет зависимость "один ко многим" между объектами, поэтому, когда один объект изменяет состояние, все его зависимости уведомляются и обновляются автоматически.
В вашем примере вы не определили ни одного наблюдателя, вместо этого у вас есть события, которые изменяют состояние самого объекта. И в методе Add() слишком много ответственности или работы.
Примером Обозревателя может служить корзина покупок (электронная коммерция), например, при изменении количества товаров объект сводной информации о заказе должен знать об этом и пересчитать сводную информацию (налоги, скидки, итого и т. Д.). Ниже приведен пример, в котором Сводка корзины и заказа обновляется как наблюдатель за элементами корзины. Он не идеален, но даст вам представление о паттерне Observer:
class Product
{
// Product properties
}
class ProductCollection
{
private List<Observer> _observers = new List<Observer>();
List<Product> _internalcol = new List<Product>();
public void Attach(Observer observer)
{
_observers.Add(observer);
}
public void Detach(Observer observer)
{
_observers.Remove(observer);
}
public void Add(Product p)
{
_internalcol.Add(p)
Notify();
}
public void Remove(Product p)
{
}
private void Notify()
{
foreach (Observer o in _observers)
{
o.Update();
}
}
}
class Cart
{
public ProductionCollection products = new ProductionCollection();
public OrderSummary summary = new OrderSummary();
public Cart()
{
products.Attach(new OrderSummary(products));
}
public void AddProduct(Product p, int count)
{
if(count > 1){
foreach(int i in count){
products.Add(p);
}
else if(count == 1){
products.Add(p);
}
else if(count == 0)
{
products.Remove(p);
}
}
}
abstract class Observer()
{
abstract void Update();
}
class OrderSummary: Observer
{
ProductionCollection _products;
// Constructor
public OrderSummary(ProductionCollection products)
{
this._products = products;
}
public override void Update()
{
//Recalculate taxes, discount etc. here.
// Update Summary object
}
public void GetSummary()
{
// return/print Summary object;
}
}
class program
{
static void Main(string[] args)
{
Cart c = new Cart();
c.products.AddProduct(
new Product()
{
Id = 50,
Name = "Watermelon",
Price = 9.21
});
}
}
Это может не скомпилировать, я написал это в блокноте.