多重继承的替代方案

2022-09-01 12:14:02

在编写 Java 20 年左右之后,我第一次希望自己拥有多重继承权。但我没有,所以我正在寻找这个具体问题的替代方案。

真正的应用程序是某种ERP,有点复杂,所以我试图将这个问题转化为汽车。这只能到此为止,但这是我能做的最好的事情。

让我们从描述汽车可以做什么的界面开始:

public interface Car {

    public String accelerate();
    public String decelerate();

    public String steerLeft();
    public String steerRight();
}

现在我们有一个基本(但不是抽象)的实现:

public class BasicCar implements Car {

    protected final String name;

    public BasicCar( String name ) {

        this.name = name;
    }

    // In the real word this method is important and does lots of stuff like calculations and caching
    protected String doDrive( String how ) {
        return name + " is " + how + "ing";
    }
    @Override
    public String accelerate() {
        return doDrive( "accelerat" );
    }
    @Override
    public String decelerate() {
        return doDrive( "decelerat" );
    }


    // This method is important, too
    protected String doSteer( String where ) {
        return name + " is steering to the " + where;
    }
    @Override
    public String steerLeft() {
        return doSteer( "left" );
    }
    @Override
    public String steerRight() {
        return doSteer( "right" );
    }
}

在现实世界中,这本身就是DAO的门面。请注意,我需要这些方法并在那里,因为这是完成一些计算,翻译和缓存等实际工作的地方。doDrivedoSteer

以及一些更具体的实现:

public class Sportscar extends BasicCar {

    public Sportscar( String name ) {
        super( name );
    }

    // I need to call the super method
    @Override
    public String doDrive( String how ) {
        return super.doDrive( how ) + " fastly";
    }
}

public class Truck extends BasicCar {

    public Truck( String name ) {
        super( name, new BasicMotor(), new TruckySteerer() );
    }

    // I need to call the super method
    @Override
    public String doSteer( String where ) {
        return super.doSteer( where ) + " carefully";
    }
}

我现在能做的是:

Car mcqueen = new Sportscar( "McQueen" );
mcqueen.steerLeft() //-> "McQueen is steering left"
mcqueen.accelerate() // -> "McQueen is accelerating fastly"

Car mack = new Truck( "Mack" );
mack.steerLeft() //-> "Mack is steering left carefully"
mack.accelerate() // -> "Mack is accelerating"

我现在想做的是将这两者组合成一个共享其功能的:

Car red = new Firetruck( "Red" );
red.steerLeft() //-> "Red is steering left *carefully*"
red.accelerate() // -> "Red is accelerating *fastly*"

我尝试过/想到什么

我可以将两者的代码复制并粘贴到一个类中。但这绝不是一个好主意。在实际的应用程序中,这几乎是代码,所以这是一个更糟糕的想法。

我认为我在这里面临着一些重大的重写/重构。

所以我可以制作和装饰器,两者都可以使用。但这不起作用,因为和是从装饰对象内部调用的,而装饰器仅适用于来自“外部”的调用。因此,我也必须将这些方法放在装饰器中,这也不是一个好主意。SportscarTruckFiretruckdoSteerdoDrive

因此,我可以使用Java8的新花哨功能,并制作和委托给这样的界面:doSteerdoDrive

@FunctionalInterface
interface Driver {
    public String doDrive( String where );
}

然后把它喂给构造函数,但是(除了变得非常复杂和得到一些其他相当讨厌的java问题)我再也无法以一种好的方式访问状态了。BasicCarfinalBasicCar

所以现在我在这里有点迷茫。任何好的想法都会得到赞赏。

编辑:举个例子,这在现实世界中看起来如何:该组可能是这样的:doSteer

class ProductImpl {
    String getTitle(){
        return getField( "title" );
    }
    String getTeaser(){
        return getField( "teaser" );
    }
    String getField( String name ){
        Locale loc = configuredLocale();
        Map vars = configuredVarialbes();
        String value = getCached( name, loc );
        value = translateVariables( value );
        value = replaceVariables( value, vars );
        // and more
    }
}

答案 1

您可以使用模式策略来定义不同的行为,并使子类实现它们。

就像这张照片:Pattern strategy

这是法语(下面的字典),但非常不言自明:

  • 从中继承的所有类都是视频游戏中使用的角色。Personnage
  • 所有实现接口 (, 、 ) 的类都在接口中定义了该方法。它们是行为。EspritCombatifDeplacementSoin
  • 该类包含右侧定义的每个接口的对象。Personnage
  • 每个字符(的子类)通过例如在构造函数中执行 a 来选择要实现的代码。Personnagecombat = new CombatCouteau();

因此,如果您只想更改所有用刀打架的家伙的行为,则只需更改 中的代码即可。CombatCouteau


字典

  • 人物 = 人物
  • 游击者 = 战士
  • 美德新 = 医生
  • Chirurgien = 外科医生
  • 库托 = 刀
  • 手枪 = 枪
  • 行军 = 步行
  • 库里尔 = 奔跑
  • 总理索因=急救
  • 手术 = 手术
  • Esprit combatif = 好斗的头脑
  • 战斗,战斗=战斗,战斗
  • déplacement, se déplacer = moving, to move
  • soin,soigner =治愈,治愈

答案 2

会做吗?它不会顺利地转化为汽车世界,但看起来适合您的任务:Compositor

public class FireTruck implements Car {

    public FireTruck( List<? extends Car> behaviors ) {
        this.behaviors = behaviors;
    }

    // I need to call the super method
    @Override
    public String doSteer( String where ) {
        String result = "":
        for (Car behavior : behaviors) result += behavior.doSteer(where);
        // post-process behavior some how to cut out infixes;
    }
}

我假设在你的实际应用中,可以在某个域对象上工作,而不是在 上工作,因此域对象的方法集应该足够丰富,以便在方法中轻松编写行为。doSteerStringdo*


推荐