在不违反 SOLID 原则的情况下使用具有不同方法名称的子类
Working with subclasses that have different method names without violating SOLID principles
//接口
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.
}
为了实现这种代码,我应该如何设计class结构?
你不应该假设在 doSomething() 中使用 .writeSong() 因为你传递的参数是 Singer,而且我们知道 Singer 只有一个方法叫做。唱歌()。这里有一些选项。
- 您应该考虑 doSomething() 在业务逻辑意义上的实际作用。也许我们可以摆脱调用 .writeSong() 因为传入的参数并不总是可以转换为 SongWriter。
- 考虑使用基础 class(例如抽象 class 或具体 class)来实现 Singer 和 SongWriter 将其作为参数数据类型传递。
- 如果您正在寻找快速修复来制作代码 运行,请参阅下文。
快速修复:
您需要首先查看 obj 是否是 SongWriter 的 instanceOf,因为传入的参数是 Singer 类型,它没有名为 .writeSong().
的方法
public void doSomething(Singer obj){
obj.sing();
//obj.writeSong(); //<--- this does not work.
if (obj instanceOf SongWriter) songWriter.writeSong();
}
这是一个快速修复。您可以从下面的帖子中看到您应该使用 instanceOf last。
- Is instanceof considered bad practice? If so, under what circumstances is instanceof still preferable?
为了快速回答问题 doSomething
调用了 sing()
和 writeSong()
方法。只有您的 SingerSongWritter
class 定义了这两个,因此是唯一可以同时执行这两个操作的 class。 objPureSinger
没有定义 writeSong
是什么,所以不知道调用时该做什么。
如果你想保留这个结构,你可以做一件事来解决这个问题,那就是在两个 class 中实现一个名为 do
的方法。在您的 PureSinger
class 中,do
只是简单地调用 sing()
但在您的 SingerSongWriter
class 中它同时调用 sing()
和 writeSong()
。最后在你的 doSomething
方法中调用 obj.do();
您可以根据业务需要设计 class。而且,很明显在
处得到编译时错误
public void doSomething(Singer obj){
obj.sing();
obj.writeSong(); //<--- compiler will complain here
}
因为Singer
没有writeSong
方法。根据您当前的设计:
- 全部
Singer
仅 sing
.
- 全部
SongWriter
仅 writeSong
.
但是,上面的none可以同时执行。所以,很明显 doSomething
直到
才有效
doSomething (SingerSongWriter obj)
因为,只有SingerSongWriter
可以同时执行。
In order to acheve this type of code, how should I design the class structure?
首先定义一个名为 Artist
的 interface
,它有一个名为 perform
的方法。接下来,定义两个子class,即Singer
和SongWriter
,每个子perform
分别实现了perform
,并包含了唱歌和写歌的代码。
以下两种设计模式可以很好地支持您的用例:
- Decorator 设计模式:在您的例子中,
Artist
是 Component,Singer
和 SongWriter
是 具体组件和ArtistDecorator
是您的抽象装饰器class。使用 ArtistDecorator
将 Singer
包装成 SongWriter
。 doSomething
方法接受一个 Artist
参数,并传递给最终修饰的 Artist
对象,该对象将 Singer
包装成 SongWriter
.
- Composite 设计模式:在您的情况下
Arist
是 组件 。 CompositeArtist
是 Composite 并且 Singer
和 SongWriter
是 Leaf 或 具体组件 classes. doSomething
方法接受一个 Artist
参数。将 CompositeArtist
的一个实例传递给它(IS-A Artist
)并且 doSomething
只是调用 perform
,它在内部遍历所有Artist
个实例一个接一个地调用它们的 perform
方法。
//接口
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.
}
为了实现这种代码,我应该如何设计class结构?
你不应该假设在 doSomething() 中使用 .writeSong() 因为你传递的参数是 Singer,而且我们知道 Singer 只有一个方法叫做。唱歌()。这里有一些选项。
- 您应该考虑 doSomething() 在业务逻辑意义上的实际作用。也许我们可以摆脱调用 .writeSong() 因为传入的参数并不总是可以转换为 SongWriter。
- 考虑使用基础 class(例如抽象 class 或具体 class)来实现 Singer 和 SongWriter 将其作为参数数据类型传递。
- 如果您正在寻找快速修复来制作代码 运行,请参阅下文。
快速修复: 您需要首先查看 obj 是否是 SongWriter 的 instanceOf,因为传入的参数是 Singer 类型,它没有名为 .writeSong().
的方法public void doSomething(Singer obj){
obj.sing();
//obj.writeSong(); //<--- this does not work.
if (obj instanceOf SongWriter) songWriter.writeSong();
}
这是一个快速修复。您可以从下面的帖子中看到您应该使用 instanceOf last。
- Is instanceof considered bad practice? If so, under what circumstances is instanceof still preferable?
为了快速回答问题 doSomething
调用了 sing()
和 writeSong()
方法。只有您的 SingerSongWritter
class 定义了这两个,因此是唯一可以同时执行这两个操作的 class。 objPureSinger
没有定义 writeSong
是什么,所以不知道调用时该做什么。
如果你想保留这个结构,你可以做一件事来解决这个问题,那就是在两个 class 中实现一个名为 do
的方法。在您的 PureSinger
class 中,do
只是简单地调用 sing()
但在您的 SingerSongWriter
class 中它同时调用 sing()
和 writeSong()
。最后在你的 doSomething
方法中调用 obj.do();
您可以根据业务需要设计 class。而且,很明显在
处得到编译时错误public void doSomething(Singer obj){
obj.sing();
obj.writeSong(); //<--- compiler will complain here
}
因为Singer
没有writeSong
方法。根据您当前的设计:
- 全部
Singer
仅sing
. - 全部
SongWriter
仅writeSong
.
但是,上面的none可以同时执行。所以,很明显 doSomething
直到
doSomething (SingerSongWriter obj)
因为,只有SingerSongWriter
可以同时执行。
In order to acheve this type of code, how should I design the class structure?
首先定义一个名为 Artist
的 interface
,它有一个名为 perform
的方法。接下来,定义两个子class,即Singer
和SongWriter
,每个子perform
分别实现了perform
,并包含了唱歌和写歌的代码。
以下两种设计模式可以很好地支持您的用例:
- Decorator 设计模式:在您的例子中,
Artist
是 Component,Singer
和SongWriter
是 具体组件和ArtistDecorator
是您的抽象装饰器class。使用ArtistDecorator
将Singer
包装成SongWriter
。doSomething
方法接受一个Artist
参数,并传递给最终修饰的Artist
对象,该对象将Singer
包装成SongWriter
. - Composite 设计模式:在您的情况下
Arist
是 组件 。CompositeArtist
是 Composite 并且Singer
和SongWriter
是 Leaf 或 具体组件 classes.doSomething
方法接受一个Artist
参数。将CompositeArtist
的一个实例传递给它(IS-AArtist
)并且doSomething
只是调用perform
,它在内部遍历所有Artist
个实例一个接一个地调用它们的perform
方法。