2011-02-24 75 views
6

想要检查这是否代表抽象工厂模式的一个好例子。 这里是主题 戴尔(厂)使得XPS(产品) 戴尔(厂),使的Inspiron(产品) 马力(厂)做特使(产品) 马力(厂)使得Presario自由人(产品)这是表示抽象工厂模式的一个很好的例子

百思买销售电脑。

//Abstract factory 
abstract class ComputerFactory 
{ 
    public abstract Computer BuildComputer(Computer.ComputerType compType); 
} 

//Concrete factory 
class Dell : ComputerFactory 
{ 
    public override Computer BuildComputer(Computer.ComputerType compType) 
    { 
     if (compType == Computer.ComputerType.xps) 
      return (new xps()); 
     else if (compType == Computer.ComputerType.inspiron) 
      return new inspiron(); 
     else 
      return null; 
    } 
} 

//Concrete factory 
class Hp : ComputerFactory 
{ 
    public override Computer BuildComputer(Computer.ComputerType compType) 
    { 
     if (compType == Computer.ComputerType.envoy) 
      return (new envoy()); 
     else if (compType == Computer.ComputerType.presario) 
      return new presario(); 
     else 
      return null; 
    } 
} 

//Abstract product 
public abstract class Computer 
{ 
    public abstract string Mhz { get; set; } 
    public enum ComputerType 
    { 
     xps, 
     inspiron, 
     envoy, 
     presario 
    } 
} 

//Concrete product for DELL 
public class xps : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for DELL 
public class inspiron : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for HP 
public class envoy : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for HP 
public class presario : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

public class BestBuy 
{ 
    ComputerFactory compFactory; 
    Computer comp; 
    public BestBuy(Computer.ComputerType compType) 
    { 
     if (compType == Computer.ComputerType.xps || compType == Computer.ComputerType.inspiron) 
      compFactory = new Dell(); 
     else 
      compFactory = new Hp(); 

     comp = compFactory.BuildComputer(compType); 
    } 

    public Computer Sell() 
    { 
     return comp; 
    } 
} 

在此先感谢。

回答

8

这是模式部分的一个很好的例子。对象的基本构造是一个体面的例子,然而,逻辑依赖于一个枚举。该枚举需要事先知道每个工厂所暴露的每种类型的计算机。

通常,使用抽象工厂的动机是从图片中抽象出这种类型的硬编码要求。而不是只有一个枚举类型,最好添加一个ComputerType类,并允许工厂返回可用类型的集合。然后您可以使用返回的ComputerType来构建新系统。

这允许您添加其他工厂而不更改API,这是抽象工厂模式的主要优点之一。阅读上的Abstract Factory Pattern - 要点之一是:

的客户端不知道(或护理),它从这些内部工厂获得哪些具体的对象,因为它仅使用其产品的通用接口。

在这种情况下,您将已知类型“硬编码”到枚举中,这违反了这部分模式。

+0

嗨,我已经添加了客户端类为好。我理解你对使用computertype作为枚举的担心。谢谢 – saidevakumar 2011-02-24 19:55:30

+1

@saidevakumar:这显示了问题。 “百思买”需要提前了解每种潜在的电脑类型。说戴尔现在除了他们的两条线外还有一台“XPQ”电脑。您必须更改API,更改客户代码等。如果您想添加第三个品牌,则必须将其添加到枚举中。通过让工厂提供他们可以创建的类型,您可以消除这种需求...... – 2011-02-24 20:09:04

+0

更糟糕的是,如果两个电脑制造商推出了同名的型号,该怎么办? – MattDavey 2011-06-07 08:10:44

3

我不是工厂模式专家,但这里有几件事情,我会做不同的:

  • 而是一个抽象类的,我会用一个接口。因此,如果“戴尔”需要从另一个类继承,它可以并且仍然可以通过实现IComputerFactory成为一个ComputerFactory。
  • 另一件小事是在你的BuildComputer函数中使用“switch”而不是“if/else if”。谁知道最终可能会有多少台电脑?
  • 您如何知道惠普和戴尔之间使用哪家混凝土厂?您可以使用“Autofac”之类的东西来“解析”使用哪个工厂。
+0

感谢您指出一些重要的项目。 – saidevakumar 2011-02-24 19:54:52

0

我认为,在您提供的场景和代码中,只有一种类型的产品,即'计算机'。没有涉及的产品家族。所以,抽象工厂模式在这里不适用。相反,工厂模式可以在这里使用。为了理解,我修改了下面的代码。

//Abstract factory 
abstract class ComputerFactory 
{ 
    public abstract Computer BuildComputer(Computer.ComputerType compType); 
} 

public class ConcreteFactory : ComputerFactory 
{ 
    public override Computer BuildComputer(Computer.ComputerType compType) 
    { 
     if (compType == Computer.ComputerType.xps) 
      return (new xps()); 
     else if (compType == Computer.ComputerType.inspiron) 
      return new inspiron(); 
     else if (compType == Computer.ComputerType.envoy) 
      return (new envoy()); 
     else if (compType == Computer.ComputerType.presario) 
      return new presario(); 
     else 
      return null; 
    } 
} 

//Abstract product 
public abstract class Computer 
{ 
    public abstract string Mhz { get; set; } 
    public enum ComputerType 
    { 
     xps, 
     inspiron, 
     envoy, 
     presario 
    } 
} 

//Concrete product for DELL 
public class xps : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for DELL 
public class inspiron : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for HP 
public class envoy : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

//Concrete product for HP 
public class presario : Computer 
{ 
    string _mhz = string.Empty; 

    public override string Mhz 
    { 
     get 
     { 
      return _mhz; 
     } 
     set 
     { 
      _mhz = value; 
     } 
    } 
} 

public class BestBuy 
{   
    ConcreteFactory compFactory; 
    Computer comp; 
    public BestBuy(Computer.ComputerType compType) 
    { 
     comp = compFactory.BuildComputer(compType);    
    } 

    public Computer Sell() 
    { 
     return comp; 
    } 
}