类、继承、接口
public class Item { public string ItemName { get; set; } public string ItemCode { get; set; } public double Price { get; set; } }
public class Items:List<Item>,IEnumerable<Item> { public Items() { this.Add(new Item() { ItemCode = "VIP_001", ItemName = "光明牛奶", Price = 36.5 }); this.Add(new Item() { ItemCode = "Normar_001", ItemName = "红富士苹果", Price = 30.5 }); this.Add(new Item() { ItemCode = "VIP_002", ItemName = "蒙牛牛奶", Price = 10 }); this.Add(new Item() { ItemCode = "Normar_002", ItemName = "进口苹果", Price = 60 }); } public IEnumerable<Item> GetVIPItems() { if (this.Count == 0) { return null; } var result = from item in this where item.ItemCode.StartsWith("VIP") select item; return result.ToList(); } public IEnumerable<Item> GetNormalItems() { if (this.Count == 0) { return null; } var result = from item in this where item.ItemCode.StartsWith("Normar") select item; return result.ToList(); } }
public class Order { public int Status { get; set; } public Items Items { get; set; } public double GetPrices() { var normalitemList =Items.GetNormalItems(); double result = 0; foreach (var item in normalitemList) { result += item.Price; } var VIPitemList = Items.GetVIPItems(); foreach (var item in VIPitemList) { result += item.Price + 20; } return result; } }
上述的Item类型违反了单一职责,只能依靠很不稳定的字符串前缀来区分,所以需要引入继承。
public class Item { public string ItemName { get; set; } public string ItemCode { get; set; } public virtual double Price { get; set; } }
public class Items : List<Item>, IEnumerable<Item> { public Items() { this.Add(new Item() { ItemCode = "VIP_001", ItemName = "光明牛奶", Price = 36.5 }); this.Add(new Item() { ItemCode = "Normar_001", ItemName = "红富士苹果", Price = 30.5 }); this.Add(new Item() { ItemCode = "VIP_002", ItemName = "蒙牛牛奶", Price = 10 }); this.Add(new Item() { ItemCode = "Normar_002", ItemName = "进口苹果", Price = 60 }); } public IEnumerable<Item> GetNormalItems() { if (this.Count == 0) { return null; } var result = from item in this where item.ItemCode.StartsWith("Normar") select item; return result.ToList(); } public IEnumerable<Item> GetVIPItems() { if (this.Count == 0) { return null; } var result = from item in this where item.ItemCode.StartsWith("VIP") select item; return result.ToList(); } }
public class VIPItem:Item { private double price; public override double Price { get { return price; } set { price = value; } } }
接口:
public interface IOperationNormalPrice { double GetPrices(Order order); double GetVipPrices(Order order); }
实现接口:
public class OperationNormalPrice:IOperationNormalPrice { public double GetPrices(Order order) { var normalitemList = order.Items.GetNormalItems(); double result = 0.0; foreach (var item in normalitemList) { //普通商品直接相加 result += item.Price; } var VIPitemList = order.Items.GetVIPItems(); foreach (var item in VIPitemList) { //VIP商品统一下调了20 result += item.Price + 20; } return result; } public double GetVipPrices(Order order) { double result = 0.0; var VIPitemList = order.Items.GetVIPItems(); foreach (var item in VIPitemList) { //VIP商品统一下调了20 result += item.Price + 20; } return result; } }
public class Order { public int Status { get; set; } public Items Items { get; set; } private IOperationNormalPrice OperationNormalPrice; public Order(IOperationNormalPrice operationNormalPrice) { this.OperationNormalPrice = operationNormalPrice; } public double GetPrices() { return this.OperationNormalPrice.GetPrices(this); } }
将复杂的计算逻辑从Order类中迁移出来,并且形成了一个独立的领域计算规则模型。
通过属性对字段进行包装的代码:
private Items items; public Items Items { get { return this.items; } set { if (value.Any(item => item.Price <= 0.0))//验证商品的价格是否正确 { return; } else { this.items = value; } } }
将代码中用到的且不变的值提取出来单独定义成变量会显示的很美观
public const string VipString = "VIP_"; public const string NormalString = "Normal_"; public Items() { this.Add(new Item() { ItemCode = string.Format(NormalString,"001"), ItemName = "光明牛奶", Price = 36.5 }); this.Add(new Item() { ItemCode = string.Format(NormalString,"002"), ItemName = "进口苹果", Price = 36.5 }); }
将大块的代码段碎片后形成高度重用的方法群。
public Order ConvertVipOrder(Order normalOrder) { if (normalOrder == null || normalOrder.Items == null || normalOrder.Items.Count == 0) { return null; } Order result=new Order(new OperationNormalPrice()) { Status = normalOrder.Status, Items=new Items() }; normalOrder.Items.ForEach(item => { result.Items.Add(new Item() { ItemCode=item.ItemCode, Price=item.Price-20, ItemName=item.ItemName }); }); return result; }
这段代码很正常,但是重用角度考虑的话,可以被分解成3块独立重用的方法,重继承的角度去看待。
public class ConvertOrderHelper { public virtual Order ConvertVipOrder(Order normalOrder) { if (this.ValidatorConvertNormalOrder(normalOrder)) { return null; } Order result = new Order(new OperationNormalPrice()) { Status = normalOrder.Status, Items = new Items() }; normalOrder.Items.ForEach(item => { result.Items.Add(this.BuildVipItemWithNormal(item)); }); return result; } protected virtual bool ValidatorConvertNormalOrder(Order normalOrder) { if (normalOrder == null || normalOrder.Items == null || normalOrder.Items.Count == 0) { return false; } else { return true; } } protected virtual Item BuildVipItemWithNormal(Item item) { Item result = new Item() { ItemCode = item.ItemCode, Price = item.Price - 20, ItemName = item.ItemName }; return result; } }
重用碎片方法的代码:
public class ConvertOrderHelper_V2:ConvertOrderHelper { protected override Item BuildVipItemWithNormal(Item item) { var vipItem = base.BuildVipItemWithNormal(item); vipItem.Price = +10; return vipItem; } protected override bool ValidatorConvertNormalOrder(Order normalOrder) { if (base.ValidatorConvertNormalOrder(normalOrder)) { if (normalOrder.Status == 2) { return true; } } return false; } }
使用委托可以轻而易举地注入一些参数化的逻辑,这些逻辑不是一个传统的值,而是一组可以改变内部运算结果的对象
自定义过滤逻辑的委托对象: