问题描述
我将尝试在一个简单示例的上下文中提出我的问题......
I'm going to try to ask my question in the context of a simple example...
假设我有一个抽象基类Car。 Car有一个基本的Engine对象。我在抽象Car类中有一个方法StartEngine(),它将引擎的起始段委托给Engine对象。
Let's say I have an abstract base class Car. Car has-a basic Engine object. I have a method StartEngine() in the abstract Car class that delegates the starting of the engine to the Engine object.
如何允许Car的子类(如法拉利)将Engine对象声明为特定类型的引擎(例如,TurboEngine)?我需要另一个Car类(TurboCar)吗?
How do I allow subclasses of Car (like Ferrari) to declare the Engine object as a specific type of engine (e.g., TurboEngine)? Do I need another Car class (TurboCar)?
我正在继承一个普通的旧引擎对象,我无法在我的作为TurboEngine中重新声明(或覆盖)它汽车子类。
I'm inheriting a plain old Engine object and I cannot re-declare (or override) it as a TurboEngine in my Car subclasses.
编辑:据我所知,我可以在我的法拉利课程中将任何Engine的子类插入myEngine参考中...但是如何调用方法只有TurboEngine暴露?因为myEngine是作为基础引擎继承的,所以不包括任何turbo内容。
I understand that I can plug any subclass of Engine into myEngine reference within my Ferrari class...but how can I call methods that only the TurboEngine exposes? Because myEngine is inherited as a base Engine, none of the turbo stuff is included.
谢谢!
推荐答案
抽象工厂模式正是为了这个问题。 Google GoF抽象工厂{您的首选语言}
The Abstract Factory pattern is precisely for this problem. Google GoF Abstract Factory {your preferred language}
在下文中,请注意如何使用具体工厂生成完整对象(enzo,civic)或您可以使用它们来生成相关对象的族(CarbonFrame + TurboEngine,WeakFrame + WeakEngine)。最终,你总是得到一个Car对象,它响应使用类型特定行为的accele()。
In the following, note how you can either use the concrete factories to produce "complete" objects (enzo, civic) or you can use them to produce "families" of related objects (CarbonFrame + TurboEngine, WeakFrame + WeakEngine). Ultimately, you always end up with a Car object that responds to accelerate() with type-specific behavior.
using System;
abstract class CarFactory
{
public static CarFactory FactoryFor(string manufacturer){
switch(manufacturer){
case "Ferrari" : return new FerrariFactory();
case "Honda" : return new HondaFactory();
default:
throw new ArgumentException("Unknown car manufacturer. Please bailout industry.");
}
}
public abstract Car createCar();
public abstract Engine createEngine();
public abstract Frame createFrame();
}
class FerrariFactory : CarFactory
{
public override Car createCar()
{
return new Ferrari(createEngine(), createFrame());
}
public override Engine createEngine()
{
return new TurboEngine();
}
public override Frame createFrame()
{
return new CarbonFrame();
}
}
class HondaFactory : CarFactory
{
public override Car createCar()
{
return new Honda(createEngine(), createFrame());
}
public override Engine createEngine()
{
return new WeakEngine();
}
public override Frame createFrame()
{
return new WeakFrame();
}
}
abstract class Car
{
private Engine engine;
private Frame frame;
public Car(Engine engine, Frame frame)
{
this.engine = engine;
this.frame = frame;
}
public void accelerate()
{
engine.setThrottle(1.0f);
frame.respondToSpeed();
}
}
class Ferrari : Car
{
public Ferrari(Engine engine, Frame frame) : base(engine, frame)
{
Console.WriteLine("Setting sticker price to $250K");
}
}
class Honda : Car
{
public Honda(Engine engine, Frame frame) : base(engine, frame)
{
Console.WriteLine("Setting sticker price to $25K");
}
}
class KitCar : Car
{
public KitCar(String name, Engine engine, Frame frame)
: base(engine, frame)
{
Console.WriteLine("Going out in the garage and building myself a " + name);
}
}
abstract class Engine
{
public void setThrottle(float percent)
{
Console.WriteLine("Stomping on accelerator!");
typeSpecificAcceleration();
}
protected abstract void typeSpecificAcceleration();
}
class TurboEngine : Engine
{
protected override void typeSpecificAcceleration()
{
Console.WriteLine("Activating turbo");
Console.WriteLine("Making noise like Barry White gargling wasps");
}
}
class WeakEngine : Engine
{
protected override void typeSpecificAcceleration()
{
Console.WriteLine("Provoking hamster to run faster");
Console.WriteLine("Whining like a dentist's drill");
}
}
abstract class Frame
{
public abstract void respondToSpeed();
}
class CarbonFrame : Frame
{
public override void respondToSpeed()
{
Console.WriteLine("Activating active suspension and extending spoilers");
}
}
class WeakFrame : Frame
{
public override void respondToSpeed()
{
Console.WriteLine("Loosening bolts and vibrating");
}
}
class TestClass
{
public static void Main()
{
CarFactory ferrariFactory = CarFactory.FactoryFor("Ferrari");
Car enzo = ferrariFactory.createCar();
enzo.accelerate();
Console.WriteLine("---");
CarFactory hondaFactory = CarFactory.FactoryFor("Honda");
Car civic = hondaFactory.createCar();
civic.accelerate();
Console.WriteLine("---");
Frame frame = hondaFactory.createFrame();
Engine engine = ferrariFactory.createEngine();
Car kitCar = new KitCar("Shaker", engine, frame);
kitCar.accelerate();
Console.WriteLine("---");
Car kitCar2 = new KitCar("LooksGreatGoesSlow", hondaFactory.createEngine(), ferrariFactory.createFrame());
kitCar2.accelerate();
}
}
这篇关于如何使用带继承的组合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!