减少工厂的参数列表

时间:2016-01-26 13:19:01

标签: c# .net domain-driven-design

我有一个场景,工厂可以制造便宜或昂贵的自行车。

var canvas = new fabric.Canvas('canvas');
canvas.setWidth(300);
canvas.setHeight(300);
var circle = new fabric.Circle({
  radius: 30,
  fill: '#f55',
  top: 100,
  left: 100
});
canvas.add(circle);
circle.hasControls = circle.hasBorders = circle.selectable = false;

var movedObject = null;
canvas.on({
  'mouse:down': function(e) {
    //If an object is selected already it'll be unselected
    if (movedObject !== null) {
        movedObject = null;
    } else {
      //If no object was selected and a click occured on an object it'll now be selected
      if (e.target) {
         movedObject = e.target;
      }
    }
  },
  'mouse:move': function(e) {
    //Moving the object along with mouse cursor
    if (movedObject !== null) {
        movedObject.left = (e.e.clientX - movedObject.width / 2);
        movedObject.top = (e.e.clientY - movedObject.height / 2);
        movedObject.setCoords();
        canvas.renderAll();
    }
  }
});

Bouth实体CheapBike和ExpensiveBike持有描述它们的ValueObject信息(保存有关它们的基本信息)。正如您所看到的,参数列表很难看,但它存在,所以参数被赋予信息构造函数

  public class BikeFactory : IBikeFactory
{
    public T GetInstance<T>(Guid userId, string bikeName, string bikeDescription, decimal value, DateTime shippingDate) where T : EntityBase
    {
        if (typeof(EntityBase).IsAssignableFrom(typeof(T)) && typeof(T) == typeof(ExpensiveBike))
        {
            Information bikeInfo = new Information(bikeName,bikeDescription, value, shippingDate);
            return (T)Activator.CreateInstance(typeof(T), userId, newIfo);
        }

        else if (typeof(EntityBase).IsAssignableFrom(typeof(T)) && typeof(T) == typeof(CheapBike))
        {
            Information bikeInfo = new Information(bikeName,bikeDescription, value, shippingDate);
            return (T)Activator.CreateInstance(typeof(T), userId, newIfo);
        }

        else return null; //for now
    }
}

和CheapBike和ExpensiveBike构造函数(保存自行车所有者的ID)

  Information(bikeName, bikeDescription, vlaue, shippingDate)

我正在寻找减少参数数量的方法,因此工厂方法GetIstance()看起来像这样:

  CheapBike(Guid owner, Information bikeInformation) // same for Expensive

问题

  1. 我应该允许客户端通过ValueObject工厂构造Information ValueObject并将其传递给Bikefactory吗?

        public T GetInstance<T>(Guid userId, Inforamtion bikeInfo) where T : EntityBase
    
  2. 或者只是允许客户端构造信息值对象?

     VOfactory.GetInstance<Inforamtion>(infoDto.name, infoDto.description, infoDto.value, infoDto.shippingDate)
     Efactory.GetInstance<CheapBike>(userId, bikeInfo)
    
  3. 这甚至是一种有效的方法吗?

3 个答案:

答案 0 :(得分:1)

  

我应该允许客户端通过ValueObject工厂构造Information ValueObject并将其传递给Bikefactory吗?

那是很多工厂,我可能会尝试通过提供过载来简化它。一个接受Information对象或所有参数的人。

public T GetInstance<T>(Guid userId, Inforamtion bikeInfo) 
    where T : EntityBase

public T GetInstance<T>(Guid userId, 
                        string name, 
                        string description, 
                        decimal value, DateTime shippingDate) 
    where T : EntityBase

然后我会允许他们在不使用工厂的情况下实例化Information对象。实际上,在ValueObject的情况下,工厂的唯一好处是实例化Information对象,这对于构造函数的用途并不是很有用。

  

或者只是允许客户端构造信息值对象?

是的,见上面的解释。

  

这甚至是一种有效的方法吗?

当然,只要工厂正确使用并且对消费者有益。

使用示例:

var bikeInfo = new Information 
{ 
    Name = infoDto.name, 
    Description = infoDto.description, 
    Value = infoDto.value, 
    ShippingDate = infoDto.shippingDate 
}
Efactory.GetInstance<CheapBike>(userId, bikeInfo);

或者

Efactory.GetInstance<CheapBike>(userId, 
                                infoDto.name,
                                infoDto.description, 
                                infoDto.value,
                                infoDto.shippingDate);

答案 1 :(得分:0)

在这种情况下,我只需将parms包装到你的dto对象中,让用户在创建时分配它们。话虽如此,我会再次查看你的设计,看看工厂在这种情况下是否真的有用。如果从工厂返回的两个对象具有完全相同的参数,那么为什么要有多个对象呢?

strncpy_s

答案 2 :(得分:0)

您想通过将Factory模式应用到您的设计中来解决哪些问题?

以下是使用工厂的两个常见动机:

  1. 减轻客户端代码选择具体实现
  2. 抽象出复杂的创作过程
  3. 据我所知,您工厂的客户正在将他们所需的具体类型传递给工厂(ExpensiveBikeCheapBike),以便排空#1。

    另外,您的工厂只会将客户端代码传递的任何内容委托给客户端选择的具体实现的构造函数。换句话说,你的工厂并没有抽象出任何额外的复杂性,因此空洞#2。

    基本上,你可能根本不应该在这里使用任何工厂,除非我错过了什么。直接调用构造函数实际上会降低设计的复杂性。

      

    &#34;我正在寻找减少参数数量的方法&#34;

    长参数列表通常表明错过了一些有意义的整体概念,但除非我们了解业务,否则我们无法为您识别这些概念。

    就像良好的OO实践一样,寻找高度凝聚力的数据成员,并尝试提出一个有意义的统一概念。您选择的概念必须为您的设计增加价值。如果概念过于抽象或任意,最好不要将信息分组,直到你搞清楚为止。

    识别这些概念的一种好方法是分析命令并查看哪些数据一起更改。例如,自行车的名称和描述可能会在一起变得很常见,因此它可能形成BikeDescriptor概念。

    E.g。

    var descriptor = new BikeDescriptor(name, description);
    var value = new Money(299.0, Currency.CAD);
    var bike = new CheapBike(id, descriptor, value, shippingDate);