I need to implement in Java an application that plays and record videos.
The video player has two states, Playing mode
and recording mode
.
While on playing mode, we can Play, Pause,Stop, Forward
andBackward
the video.
On the other hand, in recording mode we can do Record, Pause
orStop
.
Here is what I did so far:br>
I'm a little stuck. I dunno if I should create a strategy for every action of each mode or if I can make it even more simple.
I was thinking of giving the PlayingModeVideoPlayer
and RecordingModeVideoPlayer
their specefic strategies(multiples ones) but I don't know how to implement it.
thank you
Playing and Recording Modes are two independent things. I don't need to implement the transition between these two entities.

- 257
- 1
- 2
- 11
-
Does `record()` make sense in playing mode? – Thiyagu Feb 19 '18 at 06:46
-
@user7 no, its either you are in Playing Mode our Recording Mode. To test it I will have to create in instance of one of theses. – Mous Kamel Feb 19 '18 at 06:49
-
How about inheritence by composition? You know, when initializing your concrete video players, what their legal satrtigies are going to be. Provide a DS containing the legal startegies to each one of your concrete video player constructors. When changing the state of a video palyer, you can add an abstract method implementation which is valid for both your concrete video players - a verification that the set startegy is a legal one. – Rann Lifshitz Feb 19 '18 at 06:50
-
@RannLifshitz Yes it is exatly what I want to do but I don't know how to implement it. And what do you mean by DS? Should I Create something like: Play, Stop, Pause, Record, Backward and Forward and remove the two strategies I have there? – Mous Kamel Feb 19 '18 at 06:54
-
It makes sense to use states for each of the states in the Playing and Recording mode. And the actual mode switching (Playing -> Recording and vice versa) can be implemented as state itself. Can you explain how this switch happens (Playing to Recording and vice versa) – Thiyagu Feb 19 '18 at 06:56
-
Since you've mentioned that `record` shouldn't be an option in playing mode, I'm convinced that there must be two separate interface/contract (Playing and Recording) and you can use State pattern to transition among the states in each of them. – Thiyagu Feb 19 '18 at 06:58
-
Playing and Recording Modes are two independent things. I don't need to implement the transition between these two entities. @user7 – Mous Kamel Feb 19 '18 at 07:01
-
What is the external contract for the Video player? How is the user supposed to use it for playing and recording? – Thiyagu Feb 19 '18 at 07:02
-
this is an exercise to pratice OCP. All I have to do is to do is testing this app in the console. Nothing fancy. As I said before to test the playing mode. I create a PlayingModeVideoPlayer instance of VideoPlayer. – Mous Kamel Feb 19 '18 at 07:05
-
@MousKamel : DS = Data structure. A data structure of your choice, a map could work for your abstract verficatiopn check : given your legal state map, when trying to set a new state, the setting operation will fail if the state is not found in the legal states map. – Rann Lifshitz Feb 19 '18 at 07:14
-
@MousKamel : IMHO your design is simple and elegant and just requires a little polishing in regards of the binding between the states and strategies. – Rann Lifshitz Feb 19 '18 at 07:27
-
Thank you @RannLifshitz but I still have no idea how to implement that legal state map. I'll search for it now.. – Mous Kamel Feb 19 '18 at 07:32
-
@MousKamel : add an AbstractVideoPlayer class which implements VideoPlayer. Its constructor should accept a Map
parameter, for example, which will map concrete VideoPlayerState instances to their respective classes. Your abstract class should implement setVideoPlayerState and check against the map that the given concrete state class is found in the map. Then the state can be retreived from the map and its API be invoked as needed. Just a humble suggestion. – Rann Lifshitz Feb 19 '18 at 08:00 -
1`this is an exercise to pratice OCP.` -- I think your problem is too simple. OCP would need another kind of strategy in the future. Playing and Recording make sense so far, but what would be the third? I think it's not a good idea to apply OCP to a problem that has no true extension. As for State, it has the consequence `Because all state-specific code lives in a State subclass, new states and transitions can be added easily by defining new subclasses.` It's not entirely true because adding/changing transitions requires modifying the root of the hierarchy (breaks everything). – Fuhrmanator Feb 20 '18 at 16:12
-
1This is a case of patterns looking for a problem, rather than a problem looking for solution (with patterns). It's good you're trying to understand the patterns, but I think this context will cause you headaches. You can use one pattern at a time to learn them (State can work in this case, but I don't think it's such a great pattern because it's too fragile if your state machine changes -- there are more flexible ways to code a state machine). – Fuhrmanator Feb 20 '18 at 16:18
-
I felt the same thing. But I guess we can add another strategy like A dual video player or Recording while playing. – Mous Kamel Feb 20 '18 at 18:32
1 Answers
Note: From the OP, it is not clear whether it a digital video player, that automatically changes its UI based on the current mode (playing or recording) or it is an old-fashioned video player with keys (which would mean the user could click on record when playing mode).
So, this is just an idea that can help you move forward.
The VideoPlayer
interface allows a user to either start playing or recording. When one of these is chosen, the user is handed over a different interface (a contract) that specifies what actions are possible.
public interface VideoPlayer {
PlayerContext play();
RecorderContext record();
}
public class PlayerContext {
private VideoPlayer videoPlayer;
private PlayerState playerState;
public PlayerContext(VideoPlayer videoPlayer) {
this.videoPlayer = videoPlayer;
//this.playerState = ..init with PlayingState..
}
PlayerContext play() {
playerState.play();
return this;
}
PlayerContext pause() {
playerState.pause();
return this;
}
VideoPlayer stop() {
playerState.stop();
return videoPlayer;
}
PlayerContext forward() {
playerState.forward();
return this;
}
PlayerContext backward() {
playerState.backward();
return this;
}
//Methods to enable state switching
}
public class RecorderContext {
private VideoPlayer videoPlayer;
private RecorderState recorderState;
public RecorderContext(VideoPlayer videoPlayer) {
this.videoPlayer = videoPlayer;
//this.recorderState = ..init with record state
}
RecorderContext pause() {
recorderState.pause();
return this;
}
RecorderContext record() {
recorderState.record();
return this;
}
VideoPlayer stop() {
recorderState.stop();
return videoPlayer;
}
//Methods to enable state switching
}
When clicking on stop
the user can go back and choose one of the two available option - i.,e can play or record. That is why the stop
returns the base VideoPlayer
object.
public class ConcreteVideoPlayer implements VideoPlayer {
@Override
public PlayerContext play() {
return new PlayerContext(this);
}
@Override
public RecorderContext record() {
return new RecorderContext(this);
}
}
public interface PlayerState {
void play();
void pause();
VideoPlayer stop();
void forward();
void backward();
}
public interface RecorderState {
void pause();
void record();
VideoPlayer stop();
}
You can implement each of the state implementations (PlayerState
and RecorderState
) yourself.
Usage:
VideoPlayer videoPlayer = new ConcreteVideoPlayer();
PlayerContext playerContext = videoPlayer.play();
videoPlayer = playerContext.pause()
.backward()
.pause()
.play() //.play() -> Invalid state calls have to be handled by the individual state implementations
.stop();
RecorderContext recordContext = videoPlayer.record();
videoPlayer = recordContext.pause()
.record()
.pause()
.record()
.stop();
I Hope this helps!!

- 4,040
- 4
- 22
- 42

- 17,362
- 5
- 42
- 79
-
still confused honestly it is a lot different from my implementation – Mous Kamel Feb 20 '18 at 19:48
-
It did help actually but once again I changed a bit the implementation – Mous Kamel Mar 07 '18 at 22:03