-
-
Notifications
You must be signed in to change notification settings - Fork 26.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: Implement Presentation Model Pattern (#1710)
* #415 initial all componets * #415 add src and tests * #415 add diagram * #415 add README * #415 add README * #415 change pom.xml * #415 change pom.xml * #415 change pom.xml * #415 update pom.xml * #415 change some code smell * #415 change some code smell * #415 update test * #415 add javadoc * #415 remove author tag * #415 add lombok @AllArgsConstructor * #415 fix code converge * #415 fix code converge * #415 fix code converge * #415 add javadoc * #415 fix code smell * #415 fix code smell * #415 add log information * #415 remove unused import * #415 add javadoc and more test * #415 modify test * #415 fix checkstyle * #415 remove useless code and add more javadoc and test. * #415 add package-info.java. * #415 add package-info.java. * #415 add more test. * #415 fix code smell. * #415 fix code smell and increase code coverage. * #415 fix code smell. * #415 update README.md * #415 update README.md * #415 make this demo better * #415 satisfy checkstyle * #415 make some field static. * #415 make some fields static. * #415 rename some fields static. * Delete package-info.java Co-authored-by: Subhrodip Mohanta <subhrodipmohanta@gmail.com>
- Loading branch information
Showing
16 changed files
with
1,023 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
--- | ||
layout: pattern | ||
title: Presentation | ||
folder: presentation | ||
permalink: /patterns/presentation/ | ||
categories: Behavioral | ||
tags: | ||
- Decoupling | ||
--- | ||
## Also known as | ||
Application Model | ||
|
||
## Intent | ||
Presentation Model pulls the state and behavior of the view out into a model class that is part of the presentation. | ||
|
||
## Explanation | ||
|
||
Real world example | ||
|
||
> When we need to write a program with GUI, there is no need for us to put all presentation behavior in the view class. Because it will test become harder. So we can use Presentation Model Pattern to separate the behavior and view. The view only need to load the data and states from other class and show these data on the screen according to the states. | ||
In plain words | ||
|
||
> a pattern that used to divide the presentation and controlling. | ||
Code Example | ||
|
||
Class `view` is the GUI of albums. Methods `saveToPMod` and `loadFromPMod` are used to achieve synchronization. | ||
|
||
```java | ||
public class View { | ||
/** | ||
* the model that controls this view. | ||
*/ | ||
private final PresentationModel model; | ||
|
||
private TextField txtTitle; | ||
private TextField txtArtist; | ||
private JCheckBox chkClassical; | ||
private TextField txtComposer; | ||
private JList<String> albumList; | ||
private JButton apply; | ||
private JButton cancel; | ||
|
||
public View() { | ||
model = new PresentationModel(PresentationModel.albumDataSet()); | ||
} | ||
|
||
/** | ||
* save the data to PresentationModel. | ||
*/ | ||
public void saveToPMod() { | ||
LOGGER.info("Save data to PresentationModel"); | ||
model.setArtist(txtArtist.getText()); | ||
model.setTitle(txtTitle.getText()); | ||
model.setIsClassical(chkClassical.isSelected()); | ||
model.setComposer(txtComposer.getText()); | ||
} | ||
|
||
/** | ||
* load the data from PresentationModel. | ||
*/ | ||
public void loadFromPMod() { | ||
LOGGER.info("Load data from PresentationModel"); | ||
txtArtist.setText(model.getArtist()); | ||
txtTitle.setText(model.getTitle()); | ||
chkClassical.setSelected(model.getIsClassical()); | ||
txtComposer.setEditable(model.getIsClassical()); | ||
txtComposer.setText(model.getComposer()); | ||
} | ||
|
||
public void createView() { | ||
// the detail of GUI information like size, listenser and so on. | ||
} | ||
} | ||
``` | ||
|
||
Class `Album` is to store information of a album. | ||
|
||
```java | ||
public class Album { | ||
|
||
private String title; | ||
private String artist; | ||
private boolean isClassical; | ||
/** | ||
* only when the album is classical, | ||
* composer can have content. | ||
*/ | ||
private String composer; | ||
} | ||
|
||
``` | ||
|
||
Class `DisplatedAlbums` is store the information of all the albums that will be displayed on GUI. | ||
|
||
```java | ||
public class DisplayedAlbums { | ||
private final List<Album> albums; | ||
|
||
public DisplayedAlbums() { | ||
this.albums = new ArrayList<>(); | ||
} | ||
|
||
public void addAlbums(final String title, | ||
final String artist, final boolean isClassical, | ||
final String composer) { | ||
if (isClassical) { | ||
this.albums.add(new Album(title, artist, true, composer)); | ||
} else { | ||
this.albums.add(new Album(title, artist, false, "")); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Class `PresentationMod` is used to control all the action of GUI. | ||
|
||
```java | ||
public class PresentationModel { | ||
private final DisplayedAlbums data; | ||
|
||
private int selectedAlbumNumber; | ||
private Album selectedAlbum; | ||
|
||
public PresentationModel(final DisplayedAlbums dataOfAlbums) { | ||
this.data = dataOfAlbums; | ||
this.selectedAlbumNumber = 1; | ||
this.selectedAlbum = this.data.getAlbums().get(0); | ||
} | ||
|
||
/** | ||
* Changes the value of selectedAlbumNumber. | ||
* | ||
* @param albumNumber the number of album which is shown on the view. | ||
*/ | ||
public void setSelectedAlbumNumber(final int albumNumber) { | ||
LOGGER.info("Change select number from {} to {}", | ||
this.selectedAlbumNumber, albumNumber); | ||
this.selectedAlbumNumber = albumNumber; | ||
this.selectedAlbum = data.getAlbums().get(this.selectedAlbumNumber - 1); | ||
} | ||
|
||
public String getTitle() { | ||
return selectedAlbum.getTitle(); | ||
} | ||
// other get methods are like this, which are used to get information of selected album. | ||
|
||
public void setTitle(final String value) { | ||
LOGGER.info("Change album title from {} to {}", | ||
selectedAlbum.getTitle(), value); | ||
selectedAlbum.setTitle(value); | ||
} | ||
// other set methods are like this, which are used to get information of selected album. | ||
|
||
/** | ||
* Gets a list of albums. | ||
* | ||
* @return the names of all the albums. | ||
*/ | ||
public String[] getAlbumList() { | ||
var result = new String[data.getAlbums().size()]; | ||
for (var i = 0; i < result.length; i++) { | ||
result[i] = data.getAlbums().get(i).getTitle(); | ||
} | ||
return result; | ||
} | ||
} | ||
``` | ||
|
||
We can run class `App` to start this demo. the checkbox is the album classical; the first text field is the name of album artist; the second is the name of album title; the last one is the name of the composer: | ||
|
||
![](./etc/result.png) | ||
|
||
|
||
## Class diagram | ||
![](./etc/presentation.urm.png "presentation model") | ||
|
||
## Applicability | ||
Use the Presentation Model Pattern when | ||
|
||
* Testing a presentation through a GUI window is often awkward, and in some cases impossible. | ||
* Do not determine which GUI will be used. | ||
|
||
## Related patterns | ||
|
||
- [Supervising Controller](https://martinfowler.com/eaaDev/SupervisingPresenter.html) | ||
- [Passive View](https://martinfowler.com/eaaDev/PassiveScreen.html) | ||
|
||
## Credits | ||
|
||
* [Presentation Model Patterns](https://martinfowler.com/eaaDev/PresentationModel.html) | ||
|
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@startuml | ||
package com.iluwatar.presentation { | ||
class Album { | ||
~ artist : String | ||
~ composer : String | ||
~ isClassical : boolean | ||
~ rowId : int | ||
~ title : String | ||
+ Album(rowId : int, title : String, artist : String, isClassical : boolean, composer : String) | ||
} | ||
class App { | ||
+ App() | ||
+ main(args : String[]) {static} | ||
} | ||
class DsAlbum { | ||
+ albums : List<Album> | ||
+ albumsCache : List<Album> | ||
+ DsAlbum() | ||
+ acceptChanges() | ||
+ addAlbums(rowId : int, title : String, artist : String, isClassical : boolean, composer : String) | ||
} | ||
class PresentationMod { | ||
- data : DsAlbum | ||
- selectedAlbum : Album | ||
- selectedAlbumNumber : int | ||
+ PresentationMod(data : DsAlbum) | ||
+ albumDataSet() : DsAlbum {static} | ||
+ getAlbumList() : String[] | ||
+ getArtist() : String | ||
+ getComposer() : String | ||
+ getIsClassical() : boolean | ||
+ getTitle() : String | ||
+ setArtist(value : String) | ||
+ setComposer(value : String) | ||
+ setIsClassical(value : boolean) | ||
+ setSelectedAlbumNumber(selectedAlbumNumber : int) | ||
+ setTitle(value : String) | ||
} | ||
class View { | ||
~ albumList : JList<String> | ||
~ apply : JButton | ||
~ cancel : JButton | ||
~ chkClassical : JCheckBox | ||
~ model : PresentationMod | ||
~ notLoadView : boolean | ||
~ txtArtist : TextField | ||
~ txtComposer : TextField | ||
~ txtTitle : TextField | ||
+ View() | ||
+ createView() | ||
+ loadFromPMod() | ||
+ saveToPMod() | ||
} | ||
} | ||
PresentationMod --> "-selectedAlbum" Album | ||
View --> "-model" PresentationMod | ||
DsAlbum --> "-albums" Album | ||
PresentationMod --> "-data" DsAlbum | ||
@enduml |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<!-- | ||
The MIT License | ||
Copyright © 2014-2021 Ilkka Seppälä | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
--> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>com.iluwatar</groupId> | ||
<artifactId>java-design-patterns</artifactId> | ||
<version>1.25.0-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>presentation</artifactId> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-engine</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<!-- Maven assembly plugin is invoked with default setting which we have | ||
in parent pom and specifying the class having main method --> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-assembly-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<configuration> | ||
<archive> | ||
<manifest> | ||
<mainClass>com.iluwatar.presentation.App</mainClass> | ||
</manifest> | ||
</archive> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
31 changes: 31 additions & 0 deletions
31
presentation/src/main/java/com/iluwatar/presentation/Album.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.iluwatar.presentation; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
/** | ||
*A class used to store the information of album. | ||
*/ | ||
@Setter | ||
@Getter | ||
@AllArgsConstructor | ||
public class Album { | ||
/** | ||
* the title of the album. | ||
*/ | ||
private String title; | ||
/** | ||
* the artist name of the album. | ||
*/ | ||
private String artist; | ||
/** | ||
* is the album classical, true or false. | ||
*/ | ||
private boolean isClassical; | ||
/** | ||
* only when the album is classical, | ||
* composer can have content. | ||
*/ | ||
private String composer; | ||
} |
27 changes: 27 additions & 0 deletions
27
presentation/src/main/java/com/iluwatar/presentation/App.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.iluwatar.presentation; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* The Presentation model pattern is used to divide the presentation and controlling. | ||
* This demo is a used to information of some albums with GUI. | ||
*/ | ||
@Slf4j | ||
public final class App { | ||
/** | ||
* the constructor. | ||
*/ | ||
private App() { | ||
} | ||
|
||
/** | ||
* main method. | ||
* | ||
* @param args args | ||
*/ | ||
public static void main(final String[] args) { | ||
var view = new View(); | ||
view.createView(); | ||
} | ||
} | ||
|
Oops, something went wrong.