【问题标题】:Proper design of class hierarchy正确设计类层次结构
【发布时间】:2013-11-21 13:22:17
【问题描述】:

我正在尝试在 C# 中设计一个类层次结构来正确建模我的应用程序模型。 问题是我不确定哪种方法是正确的。

假设我有一个 Order 类,它应该是所有订单类型的基础(抽象)类和我在使用订单时使用的引用类型。订单类只有一个“重要”方法:我们称之为 order.PlaceOrder(),但是订单可能必须执行(或不执行)多个(正交)要求:记录下订单、下订单异步排序(PlaceOrder 方法立即返回)等。

现在,我想创建可以支持任意数量的这些要求的实际具体类。例如: GoogleOrder 类:LoggedOrder、AsyncOrder 等 AppleOrder 类:AsyncOrder MicrosoftOrder 类:订单

问题是:如果我想通过从所有“策略”派生来创建这样一个类,那么它们(除了一个)都必须是接口,而我希望继承实际实现并避免复制/粘贴代码,我不知道该怎么做。

我来自 C++ 背景,我可以从多个基类派生(或者可能使用基于策略的设计,如 Andrei Alexandrescu 在他的书中描述的),但在 C# 中我不知道该怎么做,尽管这似乎是一个非常笼统的问题,但我现在应该知道了。

非常感谢任何帮助!

【问题讨论】:

  • 这个问题比较适合程序员-programmers.stackexchange.com
  • 你可能想使用composition over inheritance
  • 或者您应该在单独的类层次结构中将订单上的实际“操作”分开。例如,您将拥有基类“OrderProcessor”,然后是派生类“AsyncOrderProcessor”和“OrderLogger”。
  • 对于一些简单的事情,比如日志记录策略,很容易在构造函数中传入一个 Logger 接口(甚至是空的)并使用它来记录,但对于其他事情,比如执行异步,我没看到...
  • 这些问题对我来说似乎不清楚。您不能将所有方法都放在基础中并根据需要从派生中调用它们吗?我什至不确定你是否解释了为什么需要派生。

标签: c# class design-patterns hierarchy


【解决方案1】:

您的设计似乎需要“装饰器模式”,装饰器模式可以灵活地动态添加职责/角色,并且可以根据您的喜好使用不同的组合,而不是使用继承。

这里是如何实现装饰器的示例:

http://alagesann.com/2013/08/16/decorator-pattern-made-easy/ http://en.wikipedia.org/wiki/Decorator_pattern

希望有帮助。

这里是您的场景的示例代码。看看有没有帮助。

 public abstract class Order
    {
        public abstract void PlaceOrder(); // log the placeing of the ordr, place the order asynchronously
    }
    public class MicrosoftOrder : Order // default order
    {
        public void PlaceOrder()
        {
            // default implementation for placing order.
        }
    }
    public class AppleOrder : Order // for asycn functionalities.
    {
        private Order order;
        public AppleOrder(Order order)
        {
            this.order = order;
        }
        public void PlaceOrder()
        {
            // Implement async functionalities.
            // you can also call default order as
            // order.PlaceOrder();
        }
    }
    public class GoogleOrder : Order // logged order
    {
        private Order order;
        public GoogleOrder(Order order)
        {
            this.order = order;
        }
        public void PlaceOrder()
        {           
            // Implement logged order
            // you can also call default order as
            // order.PlaceOrder();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Order order = new MicrosoftOrder();
            order.PlaceOrder(); // Default Order;
            Order orderWithAsync = new AppleOrder(order);
            orderWithAsync.PlaceOrder(); // Place order with asycn 

            Order orderWithAsyncAndlogging = new GoogleOrder(orderWithAsync);
            orderWithAsyncAndlogging.PlaceOrder(); // order with asynch and logging.            
        }
    }

【讨论】:

  • 嗯,从维基百科上的描述来看,这听起来正是我想要的。我需要进一步调查。
  • 我想这就是我要找的。但是,假设我只需要创建和处理 Google 订单。
  • 也许对于这个例子,三个装饰器应该重命名以反映它们的具体行为,用法应该是这样的: Order googleOrder = new LoggedOrder(new AsyncOrder(new SimpleOrder())); // 以及类似创建的其他类型的订单......另外,我在想是否有任何更漂亮的方式来实例化订单。也许链接一个 SetBehavior 方法(返回对“this”的引用)
  • 你们怎么看?另外,我很快就会接受这个答案,因为它确实解决了我的问题。
  • @user2190351 为了简化订单和一堆装饰器的创建,你可以看看 Builder 模式。有了它,订单的创建看起来像:Order order = orderBuilder.Async().Logged().GetOrder();
猜你喜欢
  • 2015-05-14
  • 2011-05-07
  • 1970-01-01
  • 2015-11-01
  • 2016-04-22
  • 2014-12-06
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多