diff --git a/role-object/README.md b/role-object/README.md
index 3f71341e1..c97177d7b 100644
--- a/role-object/README.md
+++ b/role-object/README.md
@@ -20,14 +20,10 @@ individual objects, different contexts are kept separate and system configuratio
## Applicability
Use the Role Object pattern, if:
-- you want to handle a key abstraction in different contexts and you do not want to put the resulting contextspecific interfaces into the same class interface.
-Words: 4895 Page 3 of 11
-- you want to handle the available roles dynamically so that they can be attached and removed on demand, that is
-at runtime, rather than fixing them statically at compile-time.
-- you want to treat the extensions transparently and need to preserve the logical object identity of the resulting
-object conglomerate.
-- you want to keep role/client pairs independent from each other so that changes to a role do not affect clients
-that are not interested in that role.
+- you want to handle a key abstraction in different contexts and you do not want to put the resulting context specific interfaces into the same class interface.
+- you want to handle the available roles dynamically so that they can be attached and removed on demand, that is at runtime, rather than fixing them statically at compile-time.
+- you want to treat the extensions transparently and need to preserve the logical object identity of the resultingobject conglomerate.
+- you want to keep role/client pairs independent from each other so that changes to a role do not affect clients that are not interested in that role.
## Credits
- [Hillside - Role object pattern](https://hillside.net/plop/plop97/Proceedings/riehle.pdf)
diff --git a/role-object/pom.xml b/role-object/pom.xml
index 9d7e9b88b..c9feb1419 100644
--- a/role-object/pom.xml
+++ b/role-object/pom.xml
@@ -33,6 +33,12 @@
role-object
-
+
+
+ junit
+ junit
+ test
+
+
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java
index 3dc83e470..1006fe084 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java
@@ -22,6 +22,11 @@
*/
package com.iluwatar.roleobject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.iluwatar.roleobject.Role.*;
+
/**
* The Role Object pattern suggests to model context-specific views
* of an object as separate role objects which are
@@ -34,12 +39,12 @@ package com.iluwatar.roleobject;
* investor, respectively. Both roles could as well be played by a single Customer object.
* The common superclass for customer-specific roles is provided by CustomerRole,
* which also supports the Customer interface.
+ *
* The CustomerRole class is abstract and not meant to be instantiated.
* Concrete subclasses of CustomerRole, for example Borrower or Investor,
* define and implement the interface for specific roles. It is only
* these subclasses which are instantiated at runtime.
- * The Borrower class defines the context-specific view of
- * Customer objects as needed by the loan department.
+ * The Borrower class defines the context-specific view of Customer objects as needed by the loan department.
* It defines additional operations to manage the customer’s
* credits and securities. Similarly, the Investor class adds operations specific
* to the investment department’s view of customers.
@@ -48,13 +53,40 @@ package com.iluwatar.roleobject;
* Customer instance through its Customer interface. The loan application may want to check whether the Customer
* object plays the role of Borrower.
* To this end it calls hasRole() with a suitable role specification. For the purpose of
- * our example, let’s assume we can name roles with a simple string.
- * If the Customer object can play the role named
- * “Borrower,” the loan application will ask it to return a reference to the corresponding object.
+ * our example, let’s assume we can name roles with enum.
+ * If the Customer object can play the role named “Borrower,” the loan application will ask it to return a reference to the corresponding object.
* The loan application may now use this reference to call Borrower-specific operations.
- *
*/
public class ApplicationRoleObject {
+
+ private static final Logger logger = LoggerFactory.getLogger(Role.class);
+
public static void main(String[] args) {
+ Customer customer = Customer.newCustomer(Borrower, Investor);
+
+ logger.info(" the new customer created : {}", customer);
+
+ boolean hasBorrowerRole = customer.hasRole(Borrower);
+ logger.info(" customer has a borrowed role - {}", hasBorrowerRole);
+ boolean hasInvestorRole = customer.hasRole(Investor);
+ logger.info(" customer has an investor role - {}", hasInvestorRole);
+
+ customer.getRole(Investor, InvestorRole.class)
+ .ifPresent(inv -> {
+ inv.setAmountToInvest(1000);
+ inv.setName("Billy");
+ });
+ customer.getRole(Borrower, BorrowerRole.class)
+ .ifPresent(inv -> inv.setName("Johny"));
+
+ customer.getRole(Investor, InvestorRole.class)
+ .map(InvestorRole::invest)
+ .ifPresent(logger::info);
+
+ customer.getRole(Borrower, BorrowerRole.class)
+ .map(BorrowerRole::borrow)
+ .ifPresent(logger::info);
}
+
+
}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java
index c900e3eed..8bc423e4b 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java
@@ -1,4 +1,19 @@
package com.iluwatar.roleobject;
public class BorrowerRole extends CustomerRole{
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String borrow(){
+ return String.join(" ",
+ "A borrower",name,"wants to get some money.");
+ }
+
}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java
index c9cdab4e1..c8bf5a857 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java
@@ -2,11 +2,56 @@ package com.iluwatar.roleobject;
import java.util.Optional;
+/**
+ * The main abstraction to work with Customer.
+ */
public abstract class Customer {
+ /**
+ * Add specific role @see {@link Role}
+ *
+ * @param role to add
+ * @return true if the operation has been successful otherwise false
+ */
public abstract boolean addRole(Role role);
+
+ /**
+ * Check specific role @see {@link Role}
+ *
+ * @param role to check
+ * @return true if the role exists otherwise false
+ */
+
public abstract boolean hasRole(Role role);
+
+ /**
+ * Remove specific role @see {@link Role}
+ *
+ * @param role to remove
+ * @return true if the operation has been successful otherwise false
+ */
public abstract boolean remRole(Role role);
- public abstract Optional getRole(Role role,Class expectedRole);
+
+ /**
+ * Get specific instance associated with this role @see {@link Role}
+ *
+ * @param role to get
+ * @param expectedRole instance class expected to get
+ * @return optional with value if the instance exists and corresponds expected class
+ */
+ public abstract Optional getRole(Role role, Class expectedRole);
+
+
+ public static Customer newCustomer() {
+ return new CustomerCore();
+ }
+
+ public static Customer newCustomer(Role... role) {
+ Customer customer = newCustomer();
+ for (Role r : role) {
+ customer.addRole(r);
+ }
+ return customer;
+ }
}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java
index 496022c06..3c2c7d406 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java
@@ -1,19 +1,30 @@
package com.iluwatar.roleobject;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
+import java.util.*;
+/**
+ * Core class to store different customer roles
+ *
+ * @see CustomerRole
+ * Note: not thread safe
+ */
public class CustomerCore extends Customer {
private Map roles;
+ public CustomerCore() {
+ roles = new HashMap<>();
+ }
@Override
public boolean addRole(Role role) {
- return role.instance()
- .map(rI -> roles.put(role, rI))
- .isPresent();
+ return role
+ .instance()
+ .map(inst -> {
+ roles.put(role, inst);
+ return true;
+ })
+ .orElse(false);
}
@Override
@@ -28,8 +39,15 @@ public class CustomerCore extends Customer {
@Override
public Optional getRole(Role role, Class expectedRole) {
- return Optional.ofNullable(roles.get(role))
+ return Optional
+ .ofNullable(roles.get(role))
.filter(expectedRole::isInstance)
.map(expectedRole::cast);
}
+
+ @Override
+ public String toString() {
+ String roles = Arrays.toString(this.roles.keySet().toArray());
+ return "Customer{roles=" + roles + "}";
+ }
}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java
index af2801f3d..e9806246b 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java
@@ -1,25 +1,6 @@
package com.iluwatar.roleobject;
-import java.util.Optional;
-
-public class CustomerRole extends Customer{
- @Override
- public boolean addRole(Role role) {
- return false;
- }
-
- @Override
- public boolean hasRole(Role role) {
- return false;
- }
-
- @Override
- public boolean remRole(Role role) {
- return false;
- }
-
- @Override
- public Optional getRole(Role role, Class expectedRole) {
- return Optional.empty();
- }
-}
+/**
+ * Key abstraction for segregated roles
+ */
+public abstract class CustomerRole extends CustomerCore{}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java
index a8a85d9da..4267d4d95 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java
@@ -1,4 +1,27 @@
package com.iluwatar.roleobject;
-public class InvestorRole extends CustomerRole{
+public class InvestorRole extends CustomerRole {
+ private String name;
+ private long amountToInvest;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getAmountToInvest() {
+ return amountToInvest;
+ }
+
+ public void setAmountToInvest(long amountToInvest) {
+ this.amountToInvest = amountToInvest;
+ }
+
+ public String invest() {
+ return String.join(" ",
+ "Investor", name, "has invested", String.valueOf(amountToInvest), "dollars");
+ }
}
diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java
index a59d6377b..c1934f7c5 100644
--- a/role-object/src/main/java/com/iluwatar/roleobject/Role.java
+++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java
@@ -2,27 +2,30 @@ package com.iluwatar.roleobject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sun.rmi.runtime.Log;
import java.util.Optional;
+/**
+ * Possible roles
+ */
public enum Role {
Borrower(BorrowerRole.class), Investor(InvestorRole.class);
- private Class extends Customer> typeCst;
+ private Class extends CustomerRole> typeCst;
- Role(Class extends Customer> typeCst) {
+ Role(Class extends CustomerRole> typeCst) {
this.typeCst = typeCst;
}
+
private static final Logger logger = LoggerFactory.getLogger(Role.class);
@SuppressWarnings("unchecked")
- Optional instance(){
- Class extends Customer> typeCst = this.typeCst;
+ public Optional instance() {
+ Class extends CustomerRole> typeCst = this.typeCst;
try {
return (Optional) Optional.of(typeCst.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
- logger.error("error creating an object",e);
+ logger.error("error creating an object", e);
}
return Optional.empty();
}
diff --git a/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java
new file mode 100644
index 000000000..f2c822912
--- /dev/null
+++ b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java
@@ -0,0 +1,13 @@
+package com.iluwatar.roleobject;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ApplicationRoleObjectTest {
+
+ @Test
+ public void mainTest() {
+ ApplicationRoleObject.main(new String[]{});
+ }
+}
\ No newline at end of file
diff --git a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java
new file mode 100644
index 000000000..6ba26009f
--- /dev/null
+++ b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java
@@ -0,0 +1,18 @@
+package com.iluwatar.roleobject;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class BorrowerRoleTest {
+
+ @Test
+ public void borrowTest() {
+ BorrowerRole borrowerRole = new BorrowerRole();
+ borrowerRole.setName("test");
+ String res = "A borrower test wants to get some money.";
+
+ Assert.assertEquals(borrowerRole.borrow(),res);
+ }
+}
\ No newline at end of file
diff --git a/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java
new file mode 100644
index 000000000..64712e11d
--- /dev/null
+++ b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java
@@ -0,0 +1,81 @@
+package com.iluwatar.roleobject;
+
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.junit.Assert.*;
+
+public class CustomerCoreTest {
+
+ @Test
+ public void addRole() {
+ CustomerCore core = new CustomerCore();
+ boolean add = core.addRole(Role.Borrower);
+ assertTrue(add);
+
+ }
+
+ @Test
+ public void hasRole() {
+ CustomerCore core = new CustomerCore();
+ core.addRole(Role.Borrower);
+
+ boolean has = core.hasRole(Role.Borrower);
+ assertTrue(has);
+
+ boolean notHas = core.hasRole(Role.Investor);
+ assertFalse(notHas);
+ }
+
+ @Test
+ public void remRole() {
+ CustomerCore core = new CustomerCore();
+ core.addRole(Role.Borrower);
+
+ Optional bRole = core.getRole(Role.Borrower, BorrowerRole.class);
+ assertTrue(bRole.isPresent());
+
+ boolean res = core.remRole(Role.Borrower);
+ assertTrue(res);
+
+ Optional empt = core.getRole(Role.Borrower, BorrowerRole.class);
+ assertFalse(empt.isPresent());
+
+ }
+
+ @Test
+ public void getRole() {
+ CustomerCore core = new CustomerCore();
+ core.addRole(Role.Borrower);
+
+ Optional bRole = core.getRole(Role.Borrower, BorrowerRole.class);
+ assertTrue(bRole.isPresent());
+
+ Optional nonRole = core.getRole(Role.Borrower, InvestorRole.class);
+ assertFalse(nonRole.isPresent());
+
+ Optional invRole = core.getRole(Role.Investor, InvestorRole.class);
+ assertFalse(invRole.isPresent());
+
+
+ }
+
+
+ @Test
+ public void toStringTest() {
+ CustomerCore core = new CustomerCore();
+ core.addRole(Role.Borrower);
+ assertEquals(core.toString(), "Customer{roles=[Borrower]}");
+
+ core = new CustomerCore();
+ core.addRole(Role.Investor);
+ assertEquals(core.toString(), "Customer{roles=[Investor]}");
+
+ core = new CustomerCore();
+ assertEquals(core.toString(), "Customer{roles=[]}");
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java
new file mode 100644
index 000000000..9274eae7c
--- /dev/null
+++ b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java
@@ -0,0 +1,18 @@
+package com.iluwatar.roleobject;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class InvestorRoleTest {
+
+ @Test
+ public void investTest() {
+ InvestorRole investorRole = new InvestorRole();
+ investorRole.setName("test");
+ investorRole.setAmountToInvest(10);
+ String res = "Investor test has invested 10 dollars";
+ Assert.assertEquals(investorRole.invest(), res);
+ }
+}
\ No newline at end of file
diff --git a/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java
new file mode 100644
index 000000000..dda326228
--- /dev/null
+++ b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java
@@ -0,0 +1,18 @@
+package com.iluwatar.roleobject;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.junit.Assert.*;
+
+public class RoleTest {
+
+ @Test
+ public void instanceTest() {
+ Optional instance = Role.Borrower.instance();
+ Assert.assertTrue(instance.isPresent());
+ Assert.assertEquals(instance.get().getClass(),BorrowerRole.class);
+ }
+}
\ No newline at end of file