【问题标题】:Abstraction is changed?抽象被改变了?
【发布时间】:2012-08-01 08:17:29
【问题描述】:

我的问题是,如何重新设计抽象工厂。

例如,我得到了车辆的下一个抽象:

interface IEngine { int Power(); }
class Gasoline : IEngine { public int Power() {return 150; }}
class Diesel : IEngine { public int Power() { return 50; }}

interface IFrame { string Name(); }
class Boxed : IFrame { public string Name() { return "Boxed frame"; }}
class Hat : IFrame { public string Name() { return "Hat frame"; }}

interface TransportFactory { 
  IEngine CreateEngine(); 
  IFrame CreateChassis(); 
}
class TrailerCar : TransportFactory { 
  public IEngine CreateEngine() { return new Diesel(); }
  public IFrame CreateChassis() { return new Boxed(); }
}
class PrivateCar : TransportFactory {
    public IEngine CreateEngine() { return new Gasoline(); }
    public IFrame CreateChassis() { return new Hat(); }
}

现在,我可以实例化私人或拖车。

有人建议我改变:拖车的发动机可以是涡轮增压或混合动力。仅适用于拖车!对于私家车柴油和汽油发动机仍然是常用的柴油发动机。 所以,如果我做出改变:

public enum EngineType { Hybrid, Turbo, }

interface TransportFactory
{
    IEngine CreateEngine(EngineType t);
    IFrame CreateChassis();
}

我可以添加类:

class GasolineHybrid : IEngine
{
    public int Power()
    {
        return 70;
    }
}

class GasolineTurbo : IEngine
{
    public int Power()
    {
        return 170;
    }
}

class DieselHybrid : IEngine
{
    public int Power()
    {
        return 60;
    }
}

class DieselTurbo : IEngine
{
    public int Power()
    {
        return 98;
    }
}

很好,但是(!!!)私家车没关系!!! 我可以使用什么样的设计?旧的抽象不正确?

非常感谢!!!

【问题讨论】:

    标签: oop design-patterns solid-principles abstract-factory


    【解决方案1】:

    怎么样:

    class GasolineHybridTrailerCar : TransportFactory
    {
        public IEngine CreateEngine()
        {
            return new GasolineHybrid();
        }
        ...
    }
    
    class GasolineTurboTrailerCar : TransportFactory
    {
        public IEngine CreateEngine()
        {
            return new GasolineTurbo();
        }
        ...
    }
    
    class DieselHybridTrailerCar : TransportFactory
    {
        public IEngine CreateEngine()
        {
            return new DieselHybrid();
        }
        ...
    }
    
    class DieselTurboTrailerCar : TransportFactory
    {
        public IEngine CreateEngine()
        {
            return new DieselTurbo();
        }
        ...
    }
    

    产生大量类的想法是消除客户做出错误选择的能力。既然你说混合动力和涡轮发动机对私家车没有意义,那么保持 IEngine CreateEngine(EngineType t); 将需要私人汽车工厂做出更多努力来拒绝不正确的论点。

    我不确定你是不是这个意思,但是类名表明汽车是工厂的产品。在经典关系中,它将是factory --produce--> product。你通过概括来表达它是古怪和有趣的,但其他人几乎认不出来。模式的美妙之处在于,一旦您听到它的一个单词名称,您就会对实现可能暗示的所有内部结构充满信心。

    有模式Builder。它会更适合您的设计吗?

    【讨论】:

    • 类(以您的方式)将是:类 TurboGasolineTrailerCar。制作 GasolineTurbo 对象。 HybridGasolineTrailerCar 类。制作 GasolineHybrid 对象。 TurboDieselTrailerCar 类。制作 DieselTurbo 对象。 HybridDieselTrailerCar 类。制作 DieselHybrid 对象。对我来说,这看起来是抽象问题……看起来很复杂,而且闻起来很臭……不是吗?
    • 是的,你是对的。以我的方式,拖车应该有4个班。我将编辑我的帖子
    • Roman,我认为应该还有其他抽象:在它之前是 TrailerPrivate 系列。现在,也许必须是 HybridTurbo 家族?还是汽油柴油系列?我不知道确切(缺乏经验)是哪一个
    • 在我看来,这并不重要。但我们似乎有着相同的想法
    【解决方案2】:

    请记住,参数不必是接口的一部分,它们可以传递给实现的构造函数。所以您仍然可以保留旧界面:

    interface TransportFactory
    {
        IEngine CreateEngine();
        IFrame CreateChassis();
    }
    

    但是将EngineType传递给TrailerCar构造函数:

    class TrailerCar : TransportFactory { 
      private readonly EngineType engineType;
    
      public TrailerCar(EngineType engineType)
      {
        this.engineType = engineType;
      }
    
      public IEngine CreateEngine()
      {
        if (engineType == EngineType.Hybrid) return new DieselHybrid();
        else return new DieselTurbo();
      }
    
      public IFrame CreateChassis() { return new Boxed(); }
    }
    

    【讨论】:

    • 我认为使用构造函数不是一个好主意,与其他类的构造函数不同。或者,可能对所有类使用 public XXX(EngineType engineType) 构造函数并更改接口 interface TransportFactory。但是,正如我之前所说,它与私家车无关。说真的,我现在就这样做,但我讨厌它,我想改变它。
    • @zzfima:接口的本质是允许具有不同实现的不同类公开相同的接口。因此,为每个类设置不同的构造函数是非常好的。
    • 但是,如果这一切都与抽象工厂有关,它可能不会站稳脚跟。因为 PrivateCar 类将没有参数: class PrivateCar : TransportFactory { public PrivateCar() //不需要知道 EngineType { } public IEngine CreateEngine() { return new GasolineTurbo(); //只返回一种引擎类型 } ... } 但是,它不能实现: interface TransportFactory { IEngine CreateEngine(EngineType engineType); IFrame CreateChassis(); }
    • @zzfima:如果你使用构造函数参数,你的接口将没有EngineType 用于CreateEngine,它只是IEngine CreateEngine()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 2019-03-21
    • 2012-10-04
    相关资源
    最近更新 更多