使用具有不同方法名称的子类而不违反SOLID原则

时间:2018-01-21 03:55:12

标签: java oop design-patterns polymorphism mixins

//接口

public interface Singer{
    void sing();
}
public interface SongWriter{
    void writeSong();
}

//实现

public class PureSinger implements Singer{
    void sing(){}
}
public class SingerSongWriter implements Singer, SongWriter{
    void sing(){}
    void writeSong(){}
}

//客户端代码

void methodA(){
    Singer objPureSinger = new PureSinger();
    Singer objSingerSWer = new SingerSongWriter();

    doSomething(objPureSinger);
    doSomething(objSingerSWer);
}

public void doSomething(Singer obj){
    obj.sing();
    obj.writeSong();    //<--- this does not work.
}

为了获得这种类型的代码,我应该如何设计类结构?

4 个答案:

答案 0 :(得分:1)

  

为了获得这种类型的代码,我应该如何设计类结构?

首先定义一个名为interface的{​​{1}},它有一个名为Artist的方法。接下来,定义两个子类,即performSinger,每个子类实现SongWriter并包含分别唱歌和编写歌曲的代码。

以下两种设计模式可以很好地支持您的用例:

  1. Decorator设计模式:在您的情况下,perform组件ArtistSinger具体组件< / em>和SongWriter是您的抽象装饰器类。使用ArtistDecoratorArtistDecorator打包成SingerSongWriter方法采用doSomething参数,并将最终修饰的Artist对象传递给Artist {/ 1}}。
  2. Composite设计模式:在您的情况下,Singer组件SongWriter Composite AristCompositeArtist Leaf Concrete Component 类。 Singer方法采用SongWriter参数。传递doSomething的实例( IS-A Artist),CompositeArtist只调用Artist,内部遍历所有doSomething perform 1}}实例逐个调用他们的Artist方法。

答案 1 :(得分:0)

你不应该假设在doSomething()中使用.writeSong(),因为你传递了一个参数 Singer ,我们知道Singer只有一个名为.sing的方法( )。这里有一些选择。

  1. 您应该考虑doSomething()在业务逻辑意义上的实际作用。也许我们可以摆脱调用.writeSong(),因为传入的参数并不总是可以转换为SongWriter。
  2. 考虑使用基类(例如抽象类或具体类)来实现 Singer SongWriter 以将其作为参数数据类型传递。
  3. 如果您正在寻找快速修复程序以运行代码,请参阅下文。
  4. 快速修复: 您需要首先查看obj是否是一个instanceOf SongWriter,因为传入的参数是 Singer 类型,它没有一个名为.writeSong()的方法。

    public void doSomething(Singer obj){
        obj.sing();
        //obj.writeSong();    //<--- this does not work.
        if (obj instanceOf SongWriter) songWriter.writeSong();
    }
    

    这是一个快速修复。您可以从下面的帖子中看到,您最后应该使用instanceOf。

答案 2 :(得分:0)

要快速回答问题doSomething,请同时调用sing()writeSong()方法。只有您的SingerSongWritter类同时定义了这两个类,因此唯一可以同时执行这两个操作的类。 objPureSinger没有writeSong的定义,因此不知道在调用时该怎么做。

如果你想保持这个结构,你可以做的就是修复这个问题,在两个名为do的类中实现一个方法。在PureSinger课程中,do只需拨打sing(),但在SingerSongWriter课程中,它会同时调用sing()writeSong()。最后,在您的doSomething方法中,只需致电obj.do();

答案 3 :(得分:0)

您可以根据业务需要设计课程。而且,很明显在

处获得编译时错误
public void doSomething(Singer obj){
    obj.sing();
    obj.writeSong();    //<--- compiler will complain here
}

因为,Singer没有writeSong方法。根据您目前的设计:

  1. 所有Singer只能sing
  2. 所有SongWriter只能writeSong
  3. 但是,以上都不能兼得。因此,很明显doSomething直到

    才会工作
    doSomething (SingerSongWriter obj)
    

    因为,只有SingerSongWriter才能执行这两项工作。