Das Decorator Pattern

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Das Decorator Pattern

    Moin,

    wie in einem anderen Thread (Konzept gesucht: Elternklasse erweitern) angedeutet habe ich ein bisschen mit dem Decorator Pattern gespielt.

    Der Ansatz war es, ein bestimmtes Objekt zu erweitern ohne es subclassen zu müssen.
    Im Endeffekt stelle ich fest, dass es vermutlich sinnvoller gewesen wäre, den Decorator gegen eine abstrakte Klasse oder ein Interface zu erstellen. Schließlich werde ich nur eine android.location.Location bekommen. Nichts desto trotz hoffe ich, dass der Ansatz klar wird.

    Er besteht aus zwei Komponenten: dem Interface des Decorators und einer konkreten Implementierung.

    Java-Quellcode

    1. // LocationStringDecorator.java
    2. public interface LocationStringDecorator {
    3. public String locationString();
    4. public double getLatitude();
    5. public double getLongitude();
    6. }


    Java-Quellcode

    1. // LocationDecorator.java
    2. import android.location.Location;
    3. import java.security.InvalidParameterException;
    4. public class LocationDecorator implements LocationStringDecorator {
    5. private Location decoratedLocation;
    6. public LocationDecorator(Location locationToDecorate) throws InvalidParameterException {
    7. if(locationToDecorate == null) {
    8. throw new InvalidParameterException("The given location must not be null in order to get a working decorator!");
    9. }
    10. decoratedLocation = locationToDecorate;
    11. }
    12. @Override
    13. public double getLatitude() {
    14. return decoratedLocation.getLatitude();
    15. }
    16. @Override
    17. public double getLongitude() {
    18. return decoratedLocation.getLongitude();
    19. }
    20. @Override
    21. public String locationString() {
    22. String resultString = stringForDegreeAsLatitude(getLatitude(), true);
    23. resultString += "; ";
    24. resultString += stringForDegreeAsLatitude(getLongitude(), false);
    25. return resultString;
    26. }
    27. private String stringForDegreeAsLatitude(double locationDegree, boolean isLatitude) {
    28. if(!isDegreeValidAsLatitude(locationDegree, isLatitude)) {
    29. return "Degree "+locationDegree+" is invalid!";
    30. }
    31. String resultString = orientationStringForDegreeAsLatitude(locationDegree, isLatitude);
    32. // We need to calculate with positive numbers so we'll need the absolute value first.
    33. locationDegree = Math.abs(locationDegree);
    34. double degree = Math.floor(locationDegree);
    35. resultString += (int)degree+"° ";
    36. double x = (locationDegree - degree) * 60.0;
    37. double minute = Math.floor(x);
    38. resultString += (int)minute+"' ";
    39. double second = Math.floor((x - minute) * 60.0);
    40. resultString += (int)second+'"';
    41. return resultString;
    42. }
    43. private boolean isDegreeValidAsLatitude(double degree, boolean isLatitude) {
    44. if(isLatitude) {
    45. return isLatitudeValid(degree);
    46. }
    47. else {
    48. return isLongitudeValid(degree);
    49. }
    50. }
    51. private boolean isLatitudeValid(double degree) {
    52. return (degree >= -90 && degree <= 90);
    53. }
    54. private boolean isLongitudeValid(double degree) {
    55. return (degree >= -180 && degree <= 180);
    56. }
    57. private String orientationStringForDegreeAsLatitude(double degree, boolean isLatitude) {
    58. if(isLatitude) {
    59. return orientationStringForLatitude(degree);
    60. }
    61. else {
    62. return orientationStringForLongitude(degree);
    63. }
    64. }
    65. private String orientationStringForLatitude(double latitude) {
    66. if(latitude >= 0) {
    67. return "N";
    68. }
    69. else {
    70. return "S";
    71. }
    72. }
    73. private String orientationStringForLongitude(double longitude) {
    74. if(longitude >= 0) {
    75. return "W";
    76. }
    77. else {
    78. return "E";
    79. }
    80. }
    81. }
    Alles anzeigen


    Das Einsatzgebiet sieht wie folgt aus: (Unit Tests scheinen unter Android Studio 0.3.6 defekt, deshalb via Activity)

    Java-Quellcode

    1. import android.app.Activity;
    2. import android.os.Bundle;
    3. import android.location.Location;
    4. import android.util.Log;
    5. import LocationDecorator;
    6. public class TestActivity extends Activity {
    7. public void onCreate(Bundle savedInstanceState) {
    8. super.onCreate(savedInstanceState);
    9. Location testLocation = new Location("manual");
    10. testLocation.setLatitude(52.12525);
    11. testLocation.setLongitude(-13.76584);
    12. LocationDecorator decorator = new LocationDecorator(testLocation);
    13. Log.e("INFO", decorator.locationString());
    14. testLocation.setLatitude(110);
    15. testLocation.setLongitude(-911);
    16. LocationDecorator newDecorator = new LocationDecorator(testLocation);
    17. Log.e("INFO", newDecorator.locationString());
    18. }
    19. }
    Alles anzeigen

    Output
    11-29 12:48:24.768 E/INFO﹕ N52° 7' 30"; E13° 45' 57"
    11-29 12:48:24.768 E/INFO﹕ Degree 110.0 is invalid!; Degree -911.0 is invalid!
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.

    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Marco Feltmann ()

  • Was bringt uns das jetzt?
    Nun, man könnte einen weiteren Decorator erstellen:

    Java-Quellcode

    1. // HamburgDecorator.java
    2. import android.location.Location;
    3. import java.security.InvalidParameterException;
    4. public class HamburgDecorator implements LocationStringDecorator {
    5. private Location decoratedLocation;
    6. private LocationStringDecorator decoratedDecorator;
    7. public HamburgDecorator(Location locationToDecorate) throws InvalidParameterException {
    8. if(locationToDecorate == null) {
    9. throw new InvalidParameterException("The given location must not be null in order to get a working decorator!");
    10. }
    11. decoratedLocation = locationToDecorate;
    12. }
    13. public HamburgDecorator(LocationStringDecorator decoratorToDecorate) {
    14. decoratedDecorator = decoratorToDecorate;
    15. }
    16. @Override
    17. public double getLatitude() {
    18. if(decoratedDecorator != null) {
    19. return decoratedDecorator.getLatitude();
    20. }
    21. return decoratedLocation.getLatitude();
    22. }
    23. public double getLongitude() {
    24. if(decoratedDecorator != null) {
    25. return decoratedDecorator.getLongitude();
    26. }
    27. return decoratedLocation.getLongitude();
    28. }
    29. @Override
    30. public String locationString() {
    31. String result = "";
    32. if(decoratedDecorator != null) {
    33. result += decoratedDecorator.locationString()+"\n";
    34. }
    35. if(getLatitude() <= 53.6 && getLatitude() >= 53.5 && getLongitude() <= 10.0 && getLatitude() >= 09.8) {
    36. result += "Looks like you are located in Hamburg.";
    37. }
    38. else {
    39. result += "Seems you are outside Hamburg.";
    40. }
    41. return result;
    42. }
    43. }
    Alles anzeigen


    Wenn wir das jetzt noch benutzen, dann kommt das Folgende bei rum:
    11-29 13:10:56.718 E/INFO﹕ N53° 32' 59"; W9° 58' 59"
    11-29 13:10:56.718 E/INFO﹕ Looks like you are located in Hamburg.
    11-29 13:10:56.718 E/INFO﹕ Degree 110.0 is invalid!; Degree -911.0 is invalid!
    11-29 13:10:56.718 E/INFO﹕ Seems you are outside Hamburg.
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.

    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Marco Feltmann ()

  • Und nun kommen wir zum Oberhammer: Dekorierte Dekorierer. :)

    Wir erinnern uns, folgender Code gab folgende Ausgabe:

    Java-Quellcode

    1. public class TestActivity extends Activity {
    2. public void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. Location testLocation = new Location("manual");
    5. testLocation.setLatitude(53.550000);
    6. testLocation.setLongitude(09.983333);
    7. LocationDecorator decorator = new LocationDecorator(testLocation);
    8. Log.e("INFO", decorator.locationString());
    9. HamburgDecorator inHamburg = new HamburgDecorator(testLocation);
    10. Log.e("INFO", inHamburg.locationString());
    11. testLocation.setLatitude(110);
    12. testLocation.setLongitude(-911);
    13. LocationDecorator newDecorator = new LocationDecorator(testLocation);
    14. Log.e("INFO", newDecorator.locationString());
    15. HamburgDecorator outOfHamburg = new HamburgDecorator(testLocation);
    16. Log.e("INFO", outOfHamburg.locationString());
    17. }
    18. }
    Alles anzeigen

    11-29 13:19:32.928 1254-1254/de.tagnewmedia.locationconverter.locationconverter E/INFO﹕ N53° 32' 59"; W9° 58' 59"
    11-29 13:19:32.928 1254-1254/de.tagnewmedia.locationconverter.locationconverter E/INFO﹕ Looks like you are located in Hamburg.
    11-29 13:19:32.928 1254-1254/de.tagnewmedia.locationconverter.locationconverter E/INFO﹕ Degree 110.0 is invalid!; Degree -911.0 is invalid!
    11-29 13:19:32.928 1254-1254/de.tagnewmedia.locationconverter.locationconverter E/INFO﹕ Seems you are outside Hamburg.


    Nun ändern wir aber einmal den Code:

    Java-Quellcode

    1. public class TestActivity extends Activity {
    2. public void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. Location testLocation = new Location("manual");
    5. testLocation.setLatitude(53.550000);
    6. testLocation.setLongitude(09.983333);
    7. LocationDecorator decorator = new LocationDecorator(testLocation);
    8. HamburgDecorator inHamburg = new HamburgDecorator(decorator);
    9. Log.e("INFO", inHamburg.locationString());
    10. testLocation.setLatitude(110);
    11. testLocation.setLongitude(-911);
    12. LocationDecorator newDecorator = new LocationDecorator(testLocation);
    13. HamburgDecorator outOfHamburg = new HamburgDecorator(newDecorator);
    14. Log.e("INFO", outOfHamburg.locationString());
    15. }
    16. }
    Alles anzeigen


    Wir übergeben jetzt keine Location mehr, sondern einen Decorator.
    Und die Ausgabe?
    11-29 13:25:17.588 E/INFO﹕ N53° 32' 59"; W9° 58' 59"
    Looks like you are located in Hamburg.
    11-29 13:25:17.588 1E/INFO﹕ Degree 110.0 is invalid!; Degree -911.0 is invalid!
    Seems you are outside Hamburg.
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.

    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«