您的位置:首页 > 编程语言 > ASP

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 02 业务逻辑层

2011-01-31 23:00 1061 查看
注:本例来自图书Professional ASP.NET Design Pattern,该书的亚马逊链接为:http://www.amazon.com/Professional-ASP-NET-Design-Patterns-Millett/dp/0470292784/ref=sr_1_1?ie=UTF8&qid=1296479229&sr=8-1

转载请注明本文来自博客园 http://www.cnblogs.com/charrli

业务逻辑层就是将数据的获取和数据的表现同数据的“转换方法"(业务逻辑)分离出来,单独进行建模,成为数据访问层和数据表现层的中间层。这里我们要实现的业务逻辑如前文所说:


假设数据库中有一张名为Product的表:






显示在ASPX页面上,该表如下:







这里程序试图实现的业务逻辑为:当用户选择不打折(no discount)时,售价Selling Price与数据库相同;当用户选择打折时,SellingPrice为原价95折。如果最终的SellingPrice比RRP建议零售价低,则在Discount里显示折扣了多少,同时在Savings栏里显示折扣比例。如果SellingPrice比RRP价格高或者相等,则Discount和Savings都不显示。

对业务逻辑建模如下:








这里Product类是对表Product建模得到,Price代表了表中几个与借个相关的属性。同时表明,Price中有一个field是IDiscountStrategy接口对象。该接口有两个实现,一是NullDiscountStrategy,二是TradeDiscountStrategy。下面介绍对业务逻辑层Business Logic Layer的实现步骤。注意最好是把每个类都使用一个单独的CS文件。


1. 实现IDiscountStrategy接口:


public interface IDiscountStrategy
{
decimal ApplyExtraDiscountsTo(decimal OriginalSalePrice);
}



这里接口以Strategy命名结尾,表明这里才采用了策略模式Strategy Pattern。所谓策略模式,就是让对象在运行时动态改变自己的算法和行为。在这个例子里,策略模式表现为,对象需要根据客户选择NoDiscount还是TradeDiscount来改变Selling Price的价格。具体实现上,这里使用的方法是,在Price内部有一个接口对象,它可以指向一个NullDiscountStrategy对象,也可以指向一个TradeDiscountStrategy对象,而这两个对象都有自己的不同的价格的实现方法。


2. 实现TradeDiscountStrategy类:


public class TradeDiscountStrategy : IDiscountStrategy
{
public decimal ApplyExtraDiscountsTo(decimal OriginalSalePrice)
{
decimal price = OriginalSalePrice;

price = price * 0.95M;

return price;
}
}


3. 实现NullDiscountStrategy类:


public class NullDiscountStrategy : IDiscountStrategy
{
public decimal ApplyExtraDiscountsTo(decimal OriginalSalePrice)
{
return OriginalSalePrice;
}
}


4. 实现Price类:


public class Price
{
private IDiscountStrategy _discountStrategy = new NullDiscountStrategy();
private decimal _rrp;
private decimal _sellingPrice;

public Price(decimal RRP, decimal SellingPrice)
{
_rrp = RRP;
_sellingPrice = SellingPrice;
}

public void SetDiscountStrategyTo(IDiscountStrategy DiscountStrategy)
{
_discountStrategy = DiscountStrategy;
}

public decimal SellingPrice
{
get { return _discountStrategy.ApplyExtraDiscountsTo(_sellingPrice); }
}

public decimal RRP
{
get { return _rrp; }
}

public decimal Discount
{
get {
if (RRP > SellingPrice)
return (RRP - SellingPrice);
else
return 0;}
}

public decimal Savings
{
get{
if (RRP > SellingPrice)
return 1 - (SellingPrice / RRP);
else
return 0;}
}
}

注意这里Price类将原数据库中的表的两个与价格相关的field全部实现为了Private的field,也就是说外部不能直接访问,如果要访问呢,必须要铜鼓Price类的Property才可以。这样就给程序使用get;set;方法,利用动态的Strategy来对价格进行变换提供了机会。

这里private的RRP和SellingPrice的值只能在构造函数中直接赋值,所以这两个field的值始终与数据库里的相同。

同时注意到SetDiscountStrategy方法,这给外部操作Price类提供了一机会,可以直接修改Property获得的价格的Strategy。


5. 实现Product类:


public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Price Price { get; set; }
}


6. 实现CustomType枚举类型:


public enum CustomerType
{
Standard = 0,
Trade = 1
}

这里Standard代表没有折扣,Trade代表有折扣。


7. 实现DiscountFactory类:


public static class DiscountFactory
{
public static IDiscountStrategy GetDiscountStrategyFor(CustomerType customerType)
{
switch (customerType)
{
case CustomerType.Trade:
return new TradeDiscountStrategy();
default:
return new NullDiscountStrategy();
}
}
}

这里用到了工厂模式。所谓工厂模式,就是静态类(表明该类即不能继承也不能实例,专为用作使用其内部的静态方法)内部得静态方法,可以利用一个switch结构,根据不同的输入参数,产生不同的对象。


8. 实现IProductRepository接口:


public interface IProductRepository
{
IList<Product> FindAll();
}

这里用到了仓储模式。所谓仓储模式,就是将数据库中的数据抽象为内存中的代表,从而实现了上层应用与数据库具体内容的分离。


9. 实现ProductListExtensionMethods类:


public static class ProductListExtensionMethods
{
public static void Apply(this IList<Product> products, IDiscountStrategy discountStrategy)
{
foreach (Product p in products)
{
p.Price.SetDiscountStrategyTo(discountStrategy);
}
}
}

这里使用到了拓展方法。使用拓展方法可以将要对对象使用的方法,变成对象自己拥有的方法。因为如果是要对该对象使用该方法,那么需要一个动作的发出者,但是我们显然不知道谁发出这个动作比较好,所以将这个对对象实施的方法,变成了对象自己拥有的方法。注意这里“对象”不仅仅是指已经由类所定义的对象,还包括IList这样的泛型接口。


10. 实现Product Service类:


public class ProductService
{
private IProductRepository _productRepository;

public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}

public IList<Product> GetAllProductsFor(CustomerType customerType)
{
IDiscountStrategy discountStrategy = DiscountFactory.GetDiscountStrategyFor(customerType);
IList<Product> products = _productRepository.FindAll();

products.Apply(discountStrategy);

return products;
}
}

ProductService类的作用就是,根据上层传入的CustomerType,返回本类中定义的Product的集合。


在以上十个文件都完成以后,由于使用了接口实现了层与层之间的断耦,该Project可以独立进行build。

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 01 准备工作
/article/6133832.html

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 02 业务逻辑层
/article/6133833.html

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 03 服务层
/article/6133834.html

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 04 数据访问层
/article/6133835.html

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 05 表现层
/article/6133836.html

[ASP.NET 设计模式] 用Visual Studio2010搭建一个简单的分层结构示例Step by Step —— 06 用户界面层
/article/6133837.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐