Good [your_time_of_day],
Today I have been learning about composition and factory functions in javascript (es6). I understand that composition should be preferred over inheritance and have come to agree with that (at least in javascript). Then, I realised that I have a situation where I should be using composition...
Is there a way I can change my complex, inherited structure so classes are composed of functions without having ridiculous numbers of decorators? Have I missed something about composition in general (I feel like I have)?
I have a base class AudioPlayer:
class BaseAudioPlayer {
public track;
protected seekBar;
public togglePlay() {
//
}
public seek(time) {
//some seek methods using this.seekBar
}
}
And a few player classes would extend from this like so:
class MainAudioPlayer extends BaseAudioPlayer {
public loadTrack(track) {
//This is horrible
this.track = track;
}
public setSeekBar(seekBar) {
//This is horrible
this.seekBar = seekBar
}
}
Please bare in mind I actually have a lot more methods in parent and child classes and there are many methods in some children that are not in others. Of course, there is no multiple inheritance involved but I see at some point that might become a possibility with multiple alike child players (bad!).
I could use many decorators like @playable()
@seekable()
etc. but then I see that, eventually, the number of mixins would become huge. I guess I could also use factory functions in a similar manner but see the same problem.
Full disclosure: I am using Angular2 and have cut back the code a lot to keep any discussion about which design pattern to use and not about an implementation in a specific framework.
As @JocelynLecomte commented, my question may be unclear.
The MainAudioPlayer (and other players) inherit from BaseAudioPlayer since all audio players must have togglePlay
, seek
, and a few other methods (angular2 specific so not included here).
Currently, there are three classes that inherit from BaseAudioPlayer: MainAudioPlayer, DetailAudioPlayer and CardAudioPlayer. In the future there may be more and each has there own specific methods.
Inheritance was used to avoid duplication and all players are BaseAudioPlayers. However, all players also have togglePlay
and seek
methods.
I'd like to use composition since I could see a possibility of a player that does not have a seek
method or something along those lines in the future.
It seems to that using composition would lead to a lot of boiler plate code in all player classes and I'd like to avoid this.
@playable
, @seekable
)I think if you want to reuse the base method in base class,you may want to use composition instead of inheritance (ie:define BasePlayerComponent as a property of MainAudioPlayer):
class MainAudioPlayer{
constructor(){
this.basePlayerComponent=new BasePlayerComponent();
}
public loadTrack(track) {
//This is horrible
this.track = track;
}
public setSeekBar(seekBar) {
//This is horrible
this.seekBar = seekBar
}
public togglePlay() {
this.basePlayerComponent.togglePlay();
}
public seek(time) {
this.basePlayerComponent.seek(time);
}
}