自从上次从当当买了《.NET 框架设计 - 模式、配置、工具》这本书之后,就没有停止过对这本书中所有 Demo 代码的仔细检查和推敲。

  刚买回来的时候,觉得很兴奋,有一种不小心跌入深山老林,接着万幸中捡到葵花宝典的感觉。书中的作者对本书总的概括性总结让我激动万分。再加上 微软 MVP、技术经理、架构师等一大坨专家强力推荐,我更是深信这种的内容一定会让我获益匪浅。在仔细地清扫第一章的过程中,我的表情是始终是这样的:

认可的表情

  看完第二章,我也忍了!但是随着第三章“副本”的开启,我的阅读速度开始慢慢的减缓,虽然对其中每一个程序模式的理论也都表示认可,但是每每怀着兴奋而又激动的期盼,准备见证代码奇迹的那个时候…………然后,就斯望的总觉得代码的表现力有点弱,demo 代码并没有很有效、很有力的来证明模式的特点。当我接二连三的发现其中的代码不是很给力的时候(有些甚至根本无法运行,即便我自己修改之后也无任何输出),我开始着手自己根据作者的思想写 demo 了。为此我也是挺头疼的。有时候,写一点能非常恰到好处的证明模式中的原理的代码不是件容易的事情,但是我觉得我有必要写出来,能写多少是多少,如果买了同样的书的人看到了,或许看了对他们也会有收获。

  下面我就来说说,迄今为止我所看到的有点困惑的 demo 部分,以及有些我对此觉得可以调整的地方。下面描述的我自己写的 demo 都是基于书中原有 demo 的代码所做的修改,没有原书的 demo 代码和模式原理,我也写不出。所以,还是非常感谢作者。

(1) 第三章 3.4 节 - 逻辑上下文模式

  这一小节中的逻辑代码,我还没有抽空去认真的分析,有一点是肯定的,或许是由于作者本身对这个模式再熟悉不过,脑海里对此逻辑倒背如流,所以从代码看,作者写 demo 的时候有点“模糊”。

  首先,这段代码全部自己敲一遍你会发现根本无法运行,原因是 demo 中有两个类的定义没有放出来。它们分别是:LogTrackLocation 和 TransactionActionInfo。于是,我新建了两个空类,使其编译通过。

  其次,事件绑定的方法中添加 Console.WriteLine 之后,控制台没有任何输出。

private static void soaContext_TransactionEndEvent(TransactionActionInfo arg)
{
    Console.WriteLine("......");
}
private static void soaContext_BeginRecordLogTrackEvent(LogTrackLocation arg)
{
    Console.WriteLine("............");
}

另外,在这个模式的 demo 里,我发现了两个内部实现一模一样的方法:

private void SetTicketPrice(string ticketId, int price)
{
    base.ApperceiveContext(new ServiceProxyRequest() { TicketId = ticketId, Price = price });
}
private void UpdateTicketCache(string ticketId, int price)
{
    base.ApperceiveContext(new ServiceProxyRequest() { TicketId = ticketId, Price = price });
}

(2) 第三章 3.5 节(钝化程序模式)

  这个模式很不错!谢谢清培兄。当我看到这里的时候,我也是忍不住自己改了一下。因为如果不自己写,我有点没法深刻体会这原理背后的实现。因为我觉得这个模式很实用,我一定要完全透彻的理解,从代码中理解。

[Serializable]
public class Customer
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }

    public Customer(string id, string name, string phone, string email)
    {
        Id = id;
        Name = name;
        Phone = phone;
        Email = email;
    }
    public override string ToString()
    {
        return String.Format("CUSTOMER: {0}, {1}, {2}, {3}", Id, Name, Phone, Email);
    }
}
[Serializable]
public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }

    public Product(string id, string name, double price)
    {
        Id = id;
        Name = name;
        Price = price;
    }
}
[Serializable]
public class OrderItem
{
    public Product Product { get; set; }
    public int Count { get; set; }
}

说明:上面几个是该模式操作需要用到的实体类和一些相关的枚举。基本和原书一样。接下来的也是该模式中比较重要的几个相关类。首先是 ManagerLevel 枚举,订单的审批会经过三个阶段,分别会由三位不同的 manager 进行审批。那么如何做到间断性的操作呢?也就是说如何实现书中所说的分段操作,即这个人操作一部分,接下来由另外一个人操作另一部分。非连续性分段操作是钝化模式的核心亮点。那么这个就需要对每一个阶段的操作进行验证,判断上一个操作是否完成,上一次操作是到哪里。就 demo 而言,ManagerLevel 可以枚举可以控制这个判断。

[Serializable]
public enum ManagerLevel
{
    None = 0,
    Manager1 = 1,
    Manager2 = 2,
    Manager3 = 3
}

下面是 Order 类,该类添加了 ApprovedLevel 属性,用以判断该 Order 已经经过几个步骤,被哪一个 manager 给 approve 了。

[Serializable]
public class Order
{
    public const int MAX_ITEM_COUNT = 10;
    public string Id { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }
    public ManagerLevel ApprovedLevel { get; internal set; }
}

Employee 基类,没什么特别的,只是做一个抽象,包含一些是个 employee 都该有的一些两个属性。

[Serializable]
public abstract class Employee
{
    public string Id { get; set; }
    public string Name { get; set; }

    public Employee(string id, string name)
    {
        Id = id;
        Name = name;
    }
}

下面是 Manager 类,我觉得审批的话,每一个 manager 都有 signing 的动作,唯一的区别可能就在于他们对于订单的核实内容的不同吧。

[Serializable]
public abstract class Manager : Employee
{
    public ManagerLevel Level { get; set; }
    public Manager(string id, string name, ManagerLevel level)
            : base(id, name) { Level = level; }

    public abstract bool ValidateOrder(Order order, 
            ref OrderApprovalManagementHandler approvalHandler);
    public virtual bool SignAndRecord(Order order, 
            ref OrderApprovalManagementHandler approvalHandler)
    {
        if (Level == order.ApprovedLevel && OrderApprovalHelper.SignAndRecord(order.Id))
        {
            approvalHandler -= SignAndRecord;
            Console.WriteLine("THE ORDER {0} IS SIGNED BY MANAGER {1}.", order.Id, Name);
            return true;
        }
        return false;
    }
}

下面是三个不同等级的 manager,三个 manager 对于 ValidateOrder 的审批内容略有不同。

[Serializable]
public class DepartmentManager : Manager
{
    public DepartmentManager(string id, string name, ManagerLevel level)
            : base(id, name, level) { }
    public override bool ValidateOrder(Order order, 
            ref OrderApprovalManagementHandler approvalHandler)
    {
        if (OrderApprovalHelper.ConfirmPhone(order.Customer.Phone) && 
            OrderApprovalHelper.ConfirmEmail(order.Customer.Email))
        {
            order.ApprovedLevel = Level;
            approvalHandler -= ValidateOrder;
            Console.WriteLine("THE ORDER CUSTOMER {0} INFO IS VALIDATED BY MANAGER {1}.", 
                    order.Customer.Name, Name);
            return true;
        }
        return false;
    }
}
[Serializable]
public class FinancialManager : Manager
{
    public FinancialManager(string id, string name, ManagerLevel level)
             : base(id, name, level) { }
    public override bool ValidateOrder(Order order, 
            ref OrderApprovalManagementHandler approvalHandler)
    {
        bool isPriceValid = !order.Items.Any(i => i.Product.Price <= 0);
        bool isCountValid = !order.Items.Any(i => i.Count > Order.MAX_ITEM_COUNT);
        if (isPriceValid && isCountValid)
        {
            order.ApprovedLevel = ManagerLevel.Manager2;
            approvalHandler -= ValidateOrder;
            Console.WriteLine("THE ORDER {0} IS VALIDATED BY MANAGER {1}.", order.Id, Name);
            return true;
        }
        return false;
    }
}
[Serializable]
public class GeneralManager : Manager
{
    public GeneralManager(string id, string name, ManagerLevel level)
             : base(id, name, level) { }
    public override bool ValidateOrder(Order order, 
            ref OrderApprovalManagementHandler approvalHandler)
    {
        if (order.ApprovedLevel == ManagerLevel.Manager2)
        {
            order.ApprovedLevel = ManagerLevel.Manager3;
            Console.WriteLine("THE ORDER CUSTOMER {0} INFO IS VALIDATED BY MANAGER {1}.", 
                    order.Customer.Name, Name);
            return true;
        }
        return false;
    }
}

简单的静态操作类,过。

public class OrderApprovalHelper
{
    public static bool ConfirmPhone(string phone)
    {
        return Regex.IsMatch(phone, @"[0-9]{11}");
    }
    public static bool ConfirmEmail(string email)
    {
        return Regex.IsMatch(email, @"\w+@\w+\.com");
    }
    public static bool SignAndRecord(string orderId)
    {
        return orderId != "";
    }
}

下面是委托,各个 manager 审核 order 的方法模板。

public delegate bool OrderApprovalManagementHandler(Order order, 
        ref OrderApprovalManagementHandler approvalManagementHandler);

这里重点和关键是 OrderApprovalManager 的 RunFlows 方法,该方法被“分身”了,分成了三个 switch 分支,分别处理不同的 manager 的执行流程。另外,书中原先的 ApprovalHandler 被我分成了三个,因为,如果三个审批流程被串在一个委托上,如何才能分段执行呢?这是一个疑问,我未解开,所以我使用的是分段“串烧”。

[Serializable]
public class OrderApprovalManager
{
    public OrderApprovalManagementHandler ApprovalHandler1;
    public OrderApprovalManagementHandler ApprovalHandler2;
    public OrderApprovalManagementHandler ApprovalHandler3;

    public static OrderApprovalManager CreateOrderFlow(List<Manager> managers)
    {
        OrderApprovalManager flowManager = new OrderApprovalManager();

        flowManager.ApprovalHandler1 += managers[0].ValidateOrder;
        flowManager.ApprovalHandler1 += managers[0].SignAndRecord;
        flowManager.ApprovalHandler2 += managers[1].ValidateOrder;
        flowManager.ApprovalHandler2 += managers[1].SignAndRecord;
        flowManager.ApprovalHandler3 += managers[2].ValidateOrder;
        flowManager.ApprovalHandler3 += managers[2].SignAndRecord;

        return flowManager;
    }
    public void RunFlows(Order order)
    {
        switch (order.ApprovedLevel)
        {
            case ManagerLevel.None: RunFlow1(order); break;
            case ManagerLevel.Manager1: RunFlow2(order); break;
            case ManagerLevel.Manager2: RunFlow3(order); break;
            default:
                Console.WriteLine("THE ORDER {0} IS APPROVED COMPLETELY.", order.Id); break;
        }
    }

    private void RunFlow3(Order order)
    {
        if (order.ApprovedLevel == ManagerLevel.Manager2)
            ApprovalHandler3(order, ref ApprovalHandler3);
        else Console.WriteLine("MGR3'S APPROVAL NEED MGR2'S APPROVAL COMPLETION.");
    }
    private void RunFlow2(Order order)
    {
        if (order.ApprovedLevel == ManagerLevel.Manager1)
            ApprovalHandler2(order, ref ApprovalHandler2);
        else Console.WriteLine("MGR2'S APPROVAL NEED MGR1'S APPROVAL COMPLETION.");
    }
    private void RunFlow1(Order order)
    {
        ApprovalHandler1(order, ref ApprovalHandler1);
    }
}

接着是业务流程处理类,在这里,因为需要间断性地对订单进行审核,所以,必须记录下订单的状态,所以 Order 也被序列化了。

public class OrderApprovalProcess
{
    private const string FILE_ORDER_CHECK = "ordercheck.xml";
    private const string FILE_ORDER = "order.xml";

    public OrderApprovalManager ApprovalManager { get; set; }
    public Order Order { get; set; }
    public bool IsCompleted
    {
        get
        {
            return Order.ApprovedLevel == ManagerLevel.Manager3;
        }
    }

    public static void BuildInitialData(IEnumerable<Manager> managers, Order order)
    {
        OrderApprovalProcess p = new OrderApprovalProcess(managers, order);
    }
    public OrderApprovalProcess()
    {
        Order = ReadOrder();
        ApprovalManager = ReadApprovalManager();
    }
    public OrderApprovalProcess(IEnumerable<Manager> managers, Order order)
    {
        ApprovalManager = OrderApprovalManager.CreateOrderFlow(managers.ToList());
        Order = order;

        SaveApprovalProgress();
    }
    private void WriteOrder(Order order)
    {
        using (Stream stream = File.Open(FILE_ORDER, FileMode.Create, FileAccess.ReadWrite))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, order);
            stream.Close();
        }
    }
    private void WriteApprovalManager(OrderApprovalManager manager)
    {
        using (Stream stream = File.Open(FILE_ORDER_CHECK, FileMode.Create, FileAccess.ReadWrite))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, manager);
            stream.Close();
        }
    }
    private Order ReadOrder()
    {
        using (Stream stream = File.Open(FILE_ORDER, FileMode.Open, FileAccess.ReadWrite))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            Order order = formatter.Deserialize(stream) as Order;
            stream.Close();
            return order;
        }
    }
    private OrderApprovalManager ReadApprovalManager()
    {
        using (Stream stream = File.Open(FILE_ORDER_CHECK, FileMode.Open, FileAccess.ReadWrite))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            OrderApprovalManager approveFlows = 
                    formatter.Deserialize(stream) as OrderApprovalManager;
            stream.Close();
            return approveFlows;
        }
    }
    private void SaveApprovalProgress()
    {
        WriteOrder(Order);
        WriteApprovalManager(ApprovalManager);
    }
    private void RestoreApprovalProgress()
    {
        ApprovalManager = ReadApprovalManager();
        Order = ReadOrder();
    }
    public void RunManagerApproval()
    {
        RestoreApprovalProgress();
        ApprovalManager.RunFlows(Order);
        SaveApprovalProgress();
    }
}
// 测试代码
class Program
{
    static void Main(string[] args)
    {
        try
        {
            RunStyle2();
            Console.WriteLine("DONE");
        }
        catch (Exception ex)
        {
            Console.WriteLine("ERROR:");
            Console.WriteLine(ex);
        }
        finally { Console.ReadKey(); }
    }
    static Order CreateOrder()
    {
        Order order = new Order
        {
            Id = "ORD001",
            Items = new List<OrderItem>(),
            Customer = new Customer("CST001", "Jack", "13011112222", "jack_wang@outlook.com")
        };
        order.Items.Add(new OrderItem { Product = new Product("PRD001", "电机", 700), Count = 5 });
        order.Items.Add(new OrderItem { Product = new Product("PRD002", "电瓶", 300), Count = 5 });
        order.Items.Add(new OrderItem { Product = new Product("PRD003", "碟刹", 150), Count = 10 });
        order.Items.Add(new OrderItem { Product = new Product("PRD003", "轮胎", 200), Count = 10 });
        return order;
    }
    static List<Manager> CreateManagers()
    {
        return new List<Manager>
        {
            new DepartmentManager("DPT001", "David Beckham", ManagerLevel.Manager1),
            new FinancialManager("FNC001", "Rain Giggs", ManagerLevel.Manager2),
            new GeneralManager("GNL001", "Bill Gates", ManagerLevel.Manager3)
        };
    }
    static void RunStyle1()
    {
        OrderApprovalProcess p = new OrderApprovalProcess(CreateManagers(), CreateOrder());

        for (int i = 0; !p.IsCompleted; i++)
        {
            Console.WriteLine("Step. {0}", i + 1);
            p.RunManagerApproval();
        }
    }
    static void RunStyle2()
    {
        // 构建第一步操作
        OrderApprovalProcess.BuildInitialData(CreateManagers(), CreateOrder());
        // 模拟间断性运行审批程序,一个循环就是一个阶段
        OrderApprovalProcess approvalProcess = new OrderApprovalProcess();
        for (int i = 0; !approvalProcess.IsCompleted; i++)
        {
            Console.WriteLine("Step. {0}", i + 1);
            approvalProcess.RunManagerApproval();
        }
    }
}

(3) 第三章 3.6 节(规则外挂模式)

  这一节,我改变了原本 demo 里面的例子,这个 demo 用是不是 VIP 来作为例子说明外挂模式的特点,既然是规则外挂,他的两点就在于“外挂”,既然是外挂,那就是说,应该很方便的修改规则,既然外挂是为了修改规则,那在 demo 中应该体现出这种修改,而在 demo 中貌似客户端代码中并未体现外挂修改,只是简单的创建了一个规则,感觉更像是一个简陋的工厂模式。后来我自己按照书上敲代码的时候发现,这个规则 demo 写的有点马虎了~,什么意思呢?就是说,你根本无法通过这个代码来展现这个外挂规则的修改,VIP 还是 VIP,普通用户还是普通用户,他们所能做的事情还是区别开来的。

  于是,我又开始“胡思乱想”了,我妈劝我放下这本书,把自己弄的这么头疼做什么呢?不过,在我的执着之下,我成功修改了代码,在我的 demo 里,我不再使用简单的 IsVip 和 IsNormal 作为外挂规则,因为我觉得这个根本没有 demo 的意义。我采用的是折扣场景,试想一下,一般情况下,普通用户和 VIP 用户的折扣是有区别的,而 VIP 又分普通 VIP 和 SVIP,为了更好的体现外挂模式的规则外挂特点,我使用了三个等级的 Customer,每一个 Customer 类型对应的值就是默认的打折力度,巧用枚举值作为算法一部分。不过那个方法没有用到,放着以后可以扩展。

[Serializable]
public enum CustomerType
{
    None = 0,
    SVip = 60,
    Vip = 75,
    Ordinary = 100
}

并设置了不同的促销力度:

[Serializable]
public enum PreferentialPolicy
{
    Normal,
    Discount,
    OnSale
}

根据不同的促销力度,和不同的用户等级,打折力度也是有所不同。下面是全部的代码:

[Serializable]
public class Customer
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public CustomerType CustomerType { get; set; }

    public Customer(string id, string name, string phone, string email, CustomerType type)
    {
        Id = id;
        Name = name;
        Phone = phone;
        Email = email;
        CustomerType = type;
    }
    public override string ToString()
    {
        return String.Format("CUSTOMER: {0}, {1}, {2}, {3}", Id, Name, Phone, Email);
    }
}
[Serializable]
public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }

    public Product(string id, string name, double price)
    {
        Id = id;
        Name = name;
        Price = price;
    }
}
[Serializable]
public class OrderItem
{
    public Product Product { get; set; }
    public int Count { get; set; }
}
[Serializable]
public class Order
{
    public string Id { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }

    public double TotalPrice
    {
        get
        {
            var sum = Items.Select(i => i.Product.Price * i.Count).Sum();
            return sum;
        }
    }
}
[Serializable]
public class OrderDiscountRules
{
    public PreferentialPolicy Policy { get; private set; }

    public OrderDiscountRules(PreferentialPolicy policy)
    {
        Policy = policy;
    }

    [Obsolete("暂时不用,可做扩展")]
    public double GetGeneralDiscount(Order order)
    {
        if (order.Customer.CustomerType == CustomerType.None) return 1;

        switch (Policy)
        {
            // 非打折日期
            case PreferentialPolicy.Normal:
                return (double)order.Customer.CustomerType / 100;
            // 折上折
            case PreferentialPolicy.Discount:
                return (double)(order.Customer.CustomerType - 10) / 100;
            // 疯狂大甩卖
            case PreferentialPolicy.OnSale:
                return 0.5;
            default:
                return 1;
        }
    }
    public double GetSVipDiscount()
    {
        switch (Policy)
        {
            case PreferentialPolicy.Normal: return 0.7;
            case PreferentialPolicy.Discount: return 0.6;
            case PreferentialPolicy.OnSale: return 0.5;
            default: return 1;
        }
    }
    public double GetVipDiscount()
    {
        switch (Policy)
        {
            case PreferentialPolicy.Normal: return 0.8;
            case PreferentialPolicy.Discount: return 0.7;
            case PreferentialPolicy.OnSale: return 0.5;
            default: return 1;
        }
    }
    public double GetOrdinaryDiscount()
    {
        switch (Policy)
        {
            case PreferentialPolicy.Normal: return 1;
            case PreferentialPolicy.Discount: return 0.8;
            case PreferentialPolicy.OnSale: return 0.5;
            default: return 1;
        }
    }
}
public delegate double GetOrderDiscount();

[Serializable]
public class OrderDiscountRulesManager : IDisposable
{
    public string Name { get; set; }
    public Dictionary<CustomerType, GetOrderDiscount> Rules { get; set; }

    public OrderDiscountRulesManager(string name)
    {
        Name = name;
        Rules = new Dictionary<CustomerType, GetOrderDiscount>();
    }
    public GetOrderDiscount GetOrderDiscountRule(CustomerType type)
    {
        return Rules.ContainsKey(type) ? Rules[type] : null;
    }
    public void Dispose()
    {
        Save();
    }
    public void Save()
    {
        using (Stream stream = File.Open(Name + ".xml", FileMode.Create))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
        }
    }
    public static OrderDiscountRulesManager FromName(string ruleManagerName)
    {
        using (Stream stream = File.Open(ruleManagerName + ".xml", FileMode.Open))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            return formatter.Deserialize(stream) as OrderDiscountRulesManager;
        }
    }
}
public class OrderDiscountRulesManagerFactory
{
    public static OrderDiscountRulesManager Create(PreferentialPolicy policy)
    {
        var rules = new OrderDiscountRules(policy);

        var manager = new OrderDiscountRulesManager(policy.ToString());
        manager.Rules.Add(CustomerType.Ordinary, rules.GetOrdinaryDiscount);
        manager.Rules.Add(CustomerType.Vip, rules.GetVipDiscount);
        manager.Rules.Add(CustomerType.SVip, rules.GetSVipDiscount);
        manager.Save();

        return manager;
    }
}
// 客户端:
static List<Order> GetOrders()
{
    return new List<Order>()
    {
        new Order()
        {
            Customer = new Customer("C001", "Jack", "13912439087", "jack@163.com", 
                    CustomerType.Ordinary),
            Items = new List<OrderItem>
            {
                New OrderItem { Product = new Product("P001", "永久自行车", 300), Count = 1 },
                new OrderItem { Product = new Product("P002", "台铃电动车", 4000), Count = 1 },
                new OrderItem { Product = new Product("P003", "耐克运动鞋", 500), Count = 3 }
            }
        },
        new Order()
        {
            Customer = new Customer("C002", "Paul", "13548759381", "paul@qq.com", CustomerType.Vip),
            Items = new List<OrderItem>
            {
                new OrderItem { Product = new Product("P001", "捷安特自行车", 700), Count = 1 },
                new OrderItem { Product = new Product("P002", "爱玛电动车", 3500), Count = 1 },
                new OrderItem { Product = new Product("P003", "阿迪达斯运动鞋", 500), Count = 3 }
            }
        },
        new Order()
        {
            Customer = new Customer("C003", "Mary", "13611223698", "mary@126.com", 
                    CustomerType.SVip),
            Items = new List<OrderItem>
            {
                new OrderItem { Product = new Product("P001", "凤凰自行车", 200), Count = 1 },
                new OrderItem { Product = new Product("P002", "依莱达电动车", 2800), Count = 1 },
                new OrderItem { Product = new Product("P003", "彪马运动鞋", 500), Count = 3 }
            }
        }
    };
}
static void CreateOrderDiscountManagers()
{
    OrderDiscountRulesManagerFactory.Create(PreferentialPolicy.Normal);
    OrderDiscountRulesManagerFactory.Create(PreferentialPolicy.Discount);
    OrderDiscountRulesManagerFactory.Create(PreferentialPolicy.OnSale);
}
static void Run()
{
    try
    {
        CreateOrderDiscountManagers();
        var orders = GetOrders();

        var manager = OrderDiscountRulesManager.FromName(PreferentialPolicy.Normal.ToString());
        using (OrderProcessor orderProcessor = new OrderProcessor(manager))
        {
            orders.ForEach(o => orderProcessor.Submit(o));
        }
        Console.WriteLine();
        manager = OrderDiscountRulesManager.FromName(PreferentialPolicy.Discount.ToString());
        using (OrderProcessor orderProcessor = new OrderProcessor(manager))
        {
            orders.ForEach(o => orderProcessor.Submit(o));
        }
        Console.WriteLine();
        manager = OrderDiscountRulesManager.FromName(PreferentialPolicy.OnSale.ToString());
        using (OrderProcessor orderProcessor = new OrderProcessor(manager))
        {
            orders.ForEach(o => orderProcessor.Submit(o));
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
    finally
    {
        Console.ReadKey();
    }

}

  先做这两节的改动,以后如果有更新,会陆续放上来。其实真的很不希望自己去费尽心思去写东西,不过写这些也帮助了自己加深印象,也非常感谢作者书中的模式分享。

  如有觉得不对的地方,请指正。   谢谢!