diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 00118f62c..32171a5f2 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT abstract-factory diff --git a/adapter/pom.xml b/adapter/pom.xml index fc5fdff23..3c231d60a 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT adapter diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index 815b347da..d640b890e 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT async-method-invocation diff --git a/bridge/pom.xml b/bridge/pom.xml index eee2e1c6c..ba474af55 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT bridge diff --git a/builder/pom.xml b/builder/pom.xml index c099818ce..66f679cc6 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 933518ec0..920672062 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT business-delegate diff --git a/caching/pom.xml b/caching/pom.xml index 969ca7d40..1dad83d0e 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT caching diff --git a/callback/pom.xml b/callback/pom.xml index 2c63059e4..55b1abbc5 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT callback diff --git a/chain/pom.xml b/chain/pom.xml index 007a1a224..4a0c5a96a 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT chain diff --git a/command/pom.xml b/command/pom.xml index 2ee281cee..69c499371 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT command diff --git a/composite/pom.xml b/composite/pom.xml index 3c35d1eda..551dc1f2d 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT composite diff --git a/dao/pom.xml b/dao/pom.xml index 422134ec8..3b6fc7d1e 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT dao diff --git a/decorator/pom.xml b/decorator/pom.xml index e98842da3..d8f253bd2 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT decorator diff --git a/delegation/pom.xml b/delegation/pom.xml index 62726d4ad..1cfb3e4e3 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT 4.0.0 diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index a5ce41ef5..cb210ca5a 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT dependency-injection diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index e5985a84e..e3b4c5bff 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 57da13a09..8414a6aa1 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT double-dispatch diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index d773abf0d..6627bdb1a 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT event-aggregator diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 0a77eec8e..b0b588c6b 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT event-driven-architecture diff --git a/execute-around/index.md b/execute-around/index.md index 784a02b15..f669f18ff 100644 --- a/execute-around/index.md +++ b/execute-around/index.md @@ -23,5 +23,5 @@ Use the Execute Around idiom when * you use an API that requires methods to be called in pairs such as open/close or allocate/deallocate. -##Credits +## Credits * [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1) diff --git a/execute-around/pom.xml b/execute-around/pom.xml index 569747ff2..a8654ac77 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT execute-around diff --git a/facade/pom.xml b/facade/pom.xml index e4440b234..daa3853cd 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT facade diff --git a/factory-method/pom.xml b/factory-method/pom.xml index e7a56518f..25ca9f726 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT factory-method diff --git a/feature-toggle/etc/feature-toggle.png b/feature-toggle/etc/feature-toggle.png new file mode 100644 index 000000000..5c118e57e Binary files /dev/null and b/feature-toggle/etc/feature-toggle.png differ diff --git a/feature-toggle/etc/feature-toggle.ucls b/feature-toggle/etc/feature-toggle.ucls new file mode 100644 index 000000000..538d3f416 --- /dev/null +++ b/feature-toggle/etc/feature-toggle.ucls @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature-toggle/index.md b/feature-toggle/index.md new file mode 100644 index 000000000..51747ac09 --- /dev/null +++ b/feature-toggle/index.md @@ -0,0 +1,32 @@ +--- +layout: pattern +title: Feature Toggle +folder: feature-toggle +permalink: /patterns/feature-toggle/ +categories: Behavioral +tags: + - Java + - Difficulty-Beginner +--- + +## Also known as +Feature Flag + +## Intent +Used to switch code execution paths based on properties or groupings. Allowing new features to be released, tested +and rolled out. Allowing switching back to the older feature quickly if needed. It should be noted that this pattern, +can easily introduce code complexity. There is also cause for concern that the old feature that the toggle is eventually +going to phase out is never removed, causing redundant code smells and increased maintainability. + +![alt text](./etc/feature-toggle.png "Feature Toggle") + +## Applicability +Use the Feature Toogle pattern when + +* Giving different features to different users. +* Rolling out a new feature incrementally. +* Switching between development and production environments. + +## Credits + +* [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html) \ No newline at end of file diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml new file mode 100644 index 000000000..5f732f5a3 --- /dev/null +++ b/feature-toggle/pom.xml @@ -0,0 +1,48 @@ + + + + + + java-design-patterns + com.iluwatar + 1.11.0-SNAPSHOT + + 4.0.0 + + feature-toggle + + + + + junit + junit + test + + + + \ No newline at end of file diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java new file mode 100644 index 000000000..debe99580 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java @@ -0,0 +1,96 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ + +package com.iluwatar.featuretoggle; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion; +import com.iluwatar.featuretoggle.user.User; +import com.iluwatar.featuretoggle.user.UserGroup; + +import java.util.Properties; + +/** + * The Feature Toggle pattern allows for complete code executions to be turned on or off with ease. This allows features + * to be controlled by either dynamic methods just as {@link User} information or by {@link Properties}. In the App + * below there are two examples. Firstly the {@link Properties} version of the feature toggle, where the enhanced + * version of the welcome message which is personalised is turned either on or off at instance creation. This method + * is not as dynamic as the {@link User} driven version where the feature of the personalised welcome message is + * dependant on the {@link UserGroup} the {@link User} is in. So if the user is a memeber of the + * {@link UserGroup#isPaid(User)} then they get an ehanced version of the welcome message. + * + * Note that this pattern can easily introduce code complexity, and if not kept in check can result in redundant + * unmaintained code within the codebase. + * + */ +public class App { + + /** + * Block 1 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature + * toggle to enabled. + * + * Block 2 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature + * toggle to disabled. Notice the difference with the printed welcome message the username is not included. + * + * Block 3 shows the {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} being + * set up with two users on who is on the free level, while the other is on the paid level. When the + * {@link Service#getWelcomeMessage(User)} is called with the paid {@link User} note that the welcome message + * contains their username, while the same service call with the free tier user is more generic. No username is + * printed. + * + * @see User + * @see UserGroup + * @see Service + * @see PropertiesFeatureToggleVersion + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion; + */ + public static void main(String[] args) { + + final Properties properties = new Properties(); + properties.put("enhancedWelcome", true); + Service service = new PropertiesFeatureToggleVersion(properties); + final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); + System.out.println(welcomeMessage); + + // --------------------------------------------- + + final Properties turnedOff = new Properties(); + turnedOff.put("enhancedWelcome", false); + Service turnedOffService = new PropertiesFeatureToggleVersion(turnedOff); + final String welcomeMessageturnedOff = turnedOffService.getWelcomeMessage(new User("Jamie No Code")); + System.out.println(welcomeMessageturnedOff); + + // -------------------------------------------- + + final User paidUser = new User("Jamie Coder"); + final User freeUser = new User("Alan Defect"); + + UserGroup.addUserToPaidGroup(paidUser); + UserGroup.addUserToFreeGroup(freeUser); + + final String welcomeMessagePaidUser = service.getWelcomeMessage(paidUser); + final String welcomeMessageFreeUser = service.getWelcomeMessage(freeUser); + System.out.println(welcomeMessageFreeUser); + System.out.println(welcomeMessagePaidUser); + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java new file mode 100644 index 000000000..d2542b2b7 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java @@ -0,0 +1,54 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.pattern; + +import com.iluwatar.featuretoggle.user.User; + +/** + * Simple interfaces to allow the calling of the method to generate the welcome message for a given user. While there is + * a helper method to gather the the status of the feature toggle. In some cases there is no need for the + * {@link Service#isEnhanced()} in {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} + * where the toggle is determined by the actual {@link User}. + * + * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion + * @see User + */ +public interface Service { + + /** + * Generates a welcome message for the passed user. + * + * @param user the {@link User} to be used if the message is to be personalised. + * @return Generated {@link String} welcome message + */ + String getWelcomeMessage(User user); + + /** + * Returns if the welcome message to be displayed will be the enhanced version. + * + * @return Boolean {@value true} if enhanced. + */ + boolean isEnhanced(); + +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java new file mode 100644 index 000000000..761d7d39a --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java @@ -0,0 +1,100 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.pattern.propertiesversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; + +import java.util.Properties; + +/** + * This example of the Feature Toogle pattern is less dynamic version than + * {@link com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is turned on + * or off at the time of creation of the service. This example uses simple Java {@link Properties} however it could as + * easily be done with an external configuration file loaded by Spring and so on. A good example of when to use this + * version of the feature toggle is when new features are being developed. So you could have a configuration property + * boolean named development or some sort of system environment variable. + * + * @see Service + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion + * @see User + */ +public class PropertiesFeatureToggleVersion implements Service { + + private boolean isEnhanced; + + /** + * Creates an instance of {@link PropertiesFeatureToggleVersion} using the passed {@link Properties} to determine, + * the status of the feature toggle {@link PropertiesFeatureToggleVersion#isEnhanced()}. There is also some defensive + * code to ensure the {@link Properties} passed are as expected. + * + * @param properties {@link Properties} used to configure the service and toggle features. + * @throws IllegalArgumentException when the passed {@link Properties} is not as expected + * @see Properties + */ + public PropertiesFeatureToggleVersion(final Properties properties) { + if (properties == null) { + throw new IllegalArgumentException("No Properties Provided."); + } else { + try { + isEnhanced = (boolean) properties.get("enhancedWelcome"); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid Enhancement Settings Provided."); + } + } + } + + /** + * Generate a welcome message based on the user being passed and the status of the feature toggle. If the enhanced + * version is enabled, then the message will be personalised with the name of the passed {@link User}. However if + * disabled then a generic version fo the message is returned. + * + * @param user the {@link User} to be displayed in the message if the enhanced version is enabled see + * {@link PropertiesFeatureToggleVersion#isEnhanced()}. If the enhanced version is enabled, then the + * message will be personalised with the name of the passed {@link User}. However if disabled then a + * generic version fo the message is returned. + * @return Resulting welcome message. + * @see User + */ + @Override + public String getWelcomeMessage(final User user) { + + if (isEnhanced()) { + return "Welcome " + user + ". You're using the enhanced welcome message."; + } + + return "Welcome to the application."; + } + + /** + * Method that checks if the welcome message to be returned is the enhanced venison or not. For this service it will + * see the value of the boolean that was set in the constructor + * {@link PropertiesFeatureToggleVersion#PropertiesFeatureToggleVersion(Properties)} + * + * @return Boolean value {@value true} if enhanced. + */ + @Override + public boolean isEnhanced() { + return isEnhanced; + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java new file mode 100644 index 000000000..124c9533f --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java @@ -0,0 +1,75 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.pattern.tieredversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; +import com.iluwatar.featuretoggle.user.UserGroup; + +/** + * This example of the Feature Toogle pattern shows how it could be implemented based on a {@link User}. Therefore + * showing its use within a tiered application where the paying users get access to different content or + * better versions of features. So in this instance a {@link User} is passed in and if they are found to be + * on the {@link UserGroup#isPaid(User)} they are welcomed with a personalised message. While the other is more + * generic. However this pattern is limited to simple examples such as the one below. + * + * @see Service + * @see User + * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion + * @see UserGroup + */ +public class TieredFeatureToggleVersion implements Service { + + /** + * Generates a welcome message from the passed {@link User}. The resulting message depends on the group of the + * {@link User}. So if the {@link User} is in the {@link UserGroup#paidGroup} then the enhanced version of the + * welcome message will be returned where the username is displayed. + * + * @param user the {@link User} to generate the welcome message for, different messages are displayed if the user is + * in the {@link UserGroup#isPaid(User)} or {@link UserGroup#freeGroup} + * @return Resulting welcome message. + * @see User + * @see UserGroup + */ + @Override + public String getWelcomeMessage(User user) { + if (UserGroup.isPaid(user)) { + return "You're amazing " + user + ". Thanks for paying for this awesome software."; + } + + return "I suppose you can use this software."; + } + + /** + * Method that checks if the welcome message to be returned is the enhanced version. For this instance as the logic + * is driven by the user group. This method is a little redundant. However can be used to show that there is an + * enhanced version available. + * + * @return Boolean value {@value true} if enhanced. + */ + @Override + public boolean isEnhanced() { + return true; + } + +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java new file mode 100644 index 000000000..ce7b54b7b --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.user; + +/** + * Used to demonstrate the purpose of the feature toggle. This class actually has nothing to do with the pattern. + */ +public class User { + + private String name; + + /** + * Default Constructor setting the username. + * + * @param name {@link String} to represent the name of the user. + */ + public User(String name) { + this.name = name; + } + + /** + * {@inheritDoc} + * @return The {@link String} representation of the User, in this case just return the name of the user. + */ + @Override + public String toString() { + return name; + } +} diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java new file mode 100644 index 000000000..c9d9fd027 --- /dev/null +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java @@ -0,0 +1,84 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.user; + +import java.util.ArrayList; +import java.util.List; + +/** + * Contains the lists of users of different groups paid and free. Used to demonstrate the tiered example of feature + * toggle. Allowing certain features to be available to only certain groups of users. + * + * @see User + */ +public class UserGroup { + + private static List freeGroup = new ArrayList<>(); + private static List paidGroup = new ArrayList<>(); + + + /** + * Add the passed {@link User} to the free user group list. + * + * @param user {@link User} to be added to the free group + * @throws IllegalArgumentException when user is already added to the paid group + * @see User + */ + public static void addUserToFreeGroup(final User user) throws IllegalArgumentException { + if (paidGroup.contains(user)) { + throw new IllegalArgumentException("User all ready member of paid group."); + } else { + if (!freeGroup.contains(user)) { + freeGroup.add(user); + } + } + } + + /** + * Add the passed {@link User} to the paid user group list. + * + * @param user {@link User} to be added to the paid group + * @throws IllegalArgumentException when the user is already added to the free group + * @see User + */ + public static void addUserToPaidGroup(final User user) throws IllegalArgumentException { + if (freeGroup.contains(user)) { + throw new IllegalArgumentException("User all ready member of free group."); + } else { + if (!paidGroup.contains(user)) { + paidGroup.add(user); + } + } + } + + /** + * Method to take a {@link User} to determine if the user is in the {@link UserGroup#paidGroup}. + * + * @param user {@link User} to check if they are in the {@link UserGroup#paidGroup} + * + * @return true if the {@link User} is in {@link UserGroup#paidGroup} + */ + public static boolean isPaid(User user) { + return paidGroup.contains(user); + } +} diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java new file mode 100644 index 000000000..69afc9bb4 --- /dev/null +++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java @@ -0,0 +1,69 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ + +package com.iluwatar.featuretoggle.pattern.propertiesversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; +import org.junit.Test; + +import java.util.Properties; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PropertiesFeatureToggleVersionTest { + + @Test(expected = IllegalArgumentException.class) + public void testNullPropertiesPassed() throws Exception { + new PropertiesFeatureToggleVersion(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testNonBooleanProperty() throws Exception { + final Properties properties = new Properties(); + properties.setProperty("enhancedWelcome", "Something"); + new PropertiesFeatureToggleVersion(properties); + } + + @Test + public void testFeatureTurnedOn() throws Exception { + final Properties properties = new Properties(); + properties.put("enhancedWelcome", true); + Service service = new PropertiesFeatureToggleVersion(properties); + assertTrue(service.isEnhanced()); + final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); + assertEquals("Welcome Jamie No Code. You're using the enhanced welcome message.", welcomeMessage); + } + + @Test + public void testFeatureTurnedOff() throws Exception { + final Properties properties = new Properties(); + properties.put("enhancedWelcome", false); + Service service = new PropertiesFeatureToggleVersion(properties); + assertFalse(service.isEnhanced()); + final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); + assertEquals("Welcome to the application.", welcomeMessage); + } +} \ No newline at end of file diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java new file mode 100644 index 000000000..dca1d9b82 --- /dev/null +++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java @@ -0,0 +1,64 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.pattern.tieredversion; + +import com.iluwatar.featuretoggle.pattern.Service; +import com.iluwatar.featuretoggle.user.User; +import com.iluwatar.featuretoggle.user.UserGroup; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TieredFeatureToggleVersionTest { + + final User paidUser = new User("Jamie Coder"); + final User freeUser = new User("Alan Defect"); + final Service service = new TieredFeatureToggleVersion(); + + @Before + public void setUp() throws Exception { + UserGroup.addUserToPaidGroup(paidUser); + UserGroup.addUserToFreeGroup(freeUser); + } + + @Test + public void testGetWelcomeMessageForPaidUser() throws Exception { + final String welcomeMessage = service.getWelcomeMessage(paidUser); + final String expected = "You're amazing Jamie Coder. Thanks for paying for this awesome software."; + assertEquals(expected, welcomeMessage); + } + + @Test + public void testGetWelcomeMessageForFreeUser() throws Exception { + final String welcomeMessage = service.getWelcomeMessage(freeUser); + final String expected = "I suppose you can use this software."; + assertEquals(expected, welcomeMessage); + } + + @Test + public void testIsEnhancedAlwaysTrueAsTiered() throws Exception { + assertTrue(service.isEnhanced()); + } +} \ No newline at end of file diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java new file mode 100644 index 000000000..6659815d3 --- /dev/null +++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java @@ -0,0 +1,59 @@ +/** + * The MIT License + * Copyright (c) 2014 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. + */ +package com.iluwatar.featuretoggle.user; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertTrue; + +public class UserGroupTest { + + @Test + public void testAddUserToFreeGroup() throws Exception { + User user = new User("Free User"); + UserGroup.addUserToFreeGroup(user); + assertFalse(UserGroup.isPaid(user)); + } + + @Test + public void testAddUserToPaidGroup() throws Exception { + User user = new User("Paid User"); + UserGroup.addUserToPaidGroup(user); + assertTrue(UserGroup.isPaid(user)); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddUserToPaidWhenOnFree() throws Exception { + User user = new User("Paid User"); + UserGroup.addUserToFreeGroup(user); + UserGroup.addUserToPaidGroup(user); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddUserToFreeWhenOnPaid() throws Exception { + User user = new User("Free User"); + UserGroup.addUserToPaidGroup(user); + UserGroup.addUserToFreeGroup(user); + } +} \ No newline at end of file diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 9912139f9..5faf359d1 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index e35868c3e..25182d784 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT flux diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 341d03c7c..a066c8924 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 44aed6265..8cb7ddc6d 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT front-controller diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 487afc3a0..357cabf4b 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT half-sync-half-async diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 6758d81aa..0ff3be16b 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 91efe5033..3a09ae310 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index abc18311c..2aeea6100 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT iterator diff --git a/layers/pom.xml b/layers/pom.xml index 3ac0156c0..c6e68150b 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index bbdf88995..0ca7272a0 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT lazy-loading diff --git a/mediator/pom.xml b/mediator/pom.xml index f7d1a5fd4..8e24da4b9 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT mediator diff --git a/memento/pom.xml b/memento/pom.xml index 22a67c5d9..fc78cb65b 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT memento diff --git a/message-channel/pom.xml b/message-channel/pom.xml index e8b0ca567..a6f626a11 100644 --- a/message-channel/pom.xml +++ b/message-channel/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT message-channel diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index eaf9f210d..4e8697171 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 343a39f57..c4f1c82dd 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT model-view-presenter model-view-presenter diff --git a/monostate/pom.xml b/monostate/pom.xml index 61598db4f..bb6119253 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index 22bd12861..6b07c638d 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT multiton diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 24a054c67..102c7178e 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 2cc097e92..6f476bc9b 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index d5fb3c581..6dbfc9946 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index c5b188098..451944aa5 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT naked-objects @@ -350,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index ad43bf91f..c8b483513 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT naked-objects-webapp diff --git a/null-object/pom.xml b/null-object/pom.xml index 204b874fd..e8b1d2465 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT null-object diff --git a/object-pool/pom.xml b/object-pool/pom.xml index c681d957d..5a2e4b8b6 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT object-pool diff --git a/observer/pom.xml b/observer/pom.xml index 682125cdc..c8cca3edc 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT observer diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 85f030036..0cc3bd6e8 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index 7e8cc5eb1..34f9174fa 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT pom 2014 @@ -120,6 +120,7 @@ delegation event-driven-architecture value-object + feature-toggle diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index c3f536abb..97d623b46 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 90e323241..5c00b85f9 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT producer-consumer diff --git a/property/pom.xml b/property/pom.xml index 6906bee68..a5cd459df 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT property diff --git a/prototype/pom.xml b/prototype/pom.xml index 1cc5d9599..da1aa0fd2 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT prototype diff --git a/proxy/pom.xml b/proxy/pom.xml index 890f95b5c..4640a1bba 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT proxy diff --git a/publish-subscribe/index.md b/publish-subscribe/index.md index d3b04c82d..a19aa1031 100644 --- a/publish-subscribe/index.md +++ b/publish-subscribe/index.md @@ -18,6 +18,8 @@ Broadcast messages from sender to all the interested receivers. ## Applicability Use the Publish Subscribe Channel pattern when +* two or more applications need to communicate using a messaging system for broadcasts. +======= * two or more applications need to communicate using a messaging system for broadcasts. ##Credits diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index ae90fdbf1..bfa4838e7 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT publish-subscribe diff --git a/reactor/pom.xml b/reactor/pom.xml index b22d9669d..9e228ce6e 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT reactor diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index fc6dc810a..dbfafff66 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -23,13 +23,14 @@ THE SOFTWARE. --> + 4.0.0 com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT reader-writer-lock diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java index 0dd8bb544..fd5d28ed5 100644 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.reader.writer.lock; import java.util.concurrent.ExecutorService; diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java index c88cda012..a2496a3c0 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.reader.writer.lock; import static org.mockito.Mockito.inOrder; diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java index 03b0dca51..7a1af09c0 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.reader.writer.lock; import org.junit.After; diff --git a/repository/pom.xml b/repository/pom.xml index 4b89917fe..82e4b4d67 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index f183d16a1..e79ec99ee 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/servant/pom.xml b/servant/pom.xml index bc5f6a61c..0161e71f6 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT servant diff --git a/service-layer/pom.xml b/service-layer/pom.xml index b480a75b8..ff88256a9 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index 8d388ccc8..4a64e8615 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT service-locator diff --git a/singleton/pom.xml b/singleton/pom.xml index 2375fe70f..66c02e664 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT singleton diff --git a/specification/pom.xml b/specification/pom.xml index cb7b046ae..125c34e0b 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT specification diff --git a/state/pom.xml b/state/pom.xml index ecf41e038..08b4846e6 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index 2123f0758..dde7443f9 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT step-builder diff --git a/strategy/pom.xml b/strategy/pom.xml index 9b09ede1a..0b6b2dc4e 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT strategy diff --git a/template-method/pom.xml b/template-method/pom.xml index f734cfd35..0feb89c02 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index 7eeae44e2..a2e683359 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT thread-pool diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index c6b980fb3..6c8c96b3c 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT tolerant-reader diff --git a/twin/pom.xml b/twin/pom.xml index 6c5ac7473..dc23b26ef 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT twin diff --git a/value-object/src/main/java/com/iluwatar/value/object/App.java b/value-object/src/main/java/com/iluwatar/value/object/App.java index da4c81812..f28e86bbe 100644 --- a/value-object/src/main/java/com/iluwatar/value/object/App.java +++ b/value-object/src/main/java/com/iluwatar/value/object/App.java @@ -2,18 +2,21 @@ package com.iluwatar.value.object; /** * App Class. - * */ public class App { /** * main method. + * A Value Object must check equality with equals() not ==
+ * This practice creates three HeroStats(Value object) and checks equality between those. */ public static void main(String[] args) { HeroStat statA = HeroStat.valueOf(10, 5, 0); - HeroStat statB = HeroStat.valueOf(5, 1, 8); + HeroStat statB = HeroStat.valueOf(10, 5, 0); + HeroStat statC = HeroStat.valueOf(5, 1, 8); System.out.println(statA.toString()); - // When using Value Objects do not use ==, only compare using equals(). - System.out.println("is statA and statB equal : " + statA.equals(statB)); + + System.out.println("Is statA and statB equal : " + statA.equals(statB)); + System.out.println("Is statA and statC equal : " + statA.equals(statC)); } } diff --git a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java b/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java index efcbce7ea..e7dd1edd1 100644 --- a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java +++ b/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java @@ -48,15 +48,15 @@ public class HeroStat { /* * Recommended to provide a static factory method capable of creating an instance from the formal - * string representation declared like this. public static Juice parse(String string) {} + * string representation declared like this. public static HeroStat parse(String string) {} */ // toString, hashCode, equals @Override public String toString() { - return "HeroStat [strength=" + strength + ", intelligence=" + intelligence + ", luck=" + luck - + "]"; + return "HeroStat [strength=" + strength + ", intelligence=" + intelligence + + ", luck=" + luck + "]"; } @Override @@ -94,6 +94,6 @@ public class HeroStat { } - // The clone() method should not be public + // The clone() method should not be public. Just don't override it. } diff --git a/value-object/src/test/java/com/iluwatar/value/object/AppTest.java b/value-object/src/test/java/com/iluwatar/value/object/AppTest.java new file mode 100644 index 000000000..aed3c2f20 --- /dev/null +++ b/value-object/src/test/java/com/iluwatar/value/object/AppTest.java @@ -0,0 +1,15 @@ +package com.iluwatar.value.object; + +import org.junit.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java b/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java index f8785e538..162d9e736 100644 --- a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java +++ b/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java @@ -15,9 +15,10 @@ import org.junit.Test; public class HeroStatTest { /** - * Tester for equals() and hashCode() methods of a class. + * Tester for equals() and hashCode() methods of a class. Using guava's EqualsTester * - * @see http://www.javadoc.io/doc/com.google.guava/guava-testlib/19.0 + * @see http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/ + * EqualsTester.html */ @Test public void testEquals() { diff --git a/visitor/pom.xml b/visitor/pom.xml index d46a7e0f7..cdffb0151 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.10.0-SNAPSHOT + 1.11.0-SNAPSHOT visitor