I am confused about state pattern implementation. Under this pattern, we should extract state management into separate classes. At first glance it allows us to avoid big if ... else ... constructions inside domain entity and it really powerful advantage. We can move all condition checks into state classes and clear our domain entity class.
But how to modify the data encapsulated in the domain object without encapsulation principle violation?
For example, consider the Account entity. In a simplified way, it has two possible states - Active and Blocked and methods for money deposit and withdrawal.
Under the state pattern, we should delegate deposit and withdrawal responsibilities to state classes. UML diagram here.
But how can we modify the money and state fields from AccountState implementations? I see only the way where I have public setters for it. But it violates the encapsulation principle. With this approach, I can also change private fields to the public.
Code example:
class Account {
private int money;
private AccountState state;
public Account() {
this.money = 0;
this.state = new Active();
}
public void deposit(int amount) {
this.state.deposit(this, amount);
}
public void withdraw(int amount) {
this.state.withdraw(this, amount);
}
public int getMoney() {
return this.money;
}
public AccountState getState() {
return this.state;
}
}
interface AccountState {
public void deposit(Account account, int amount);
public void withdraw(Account account, int amount);
}
class Active implements AccountState {
public void deposit(Account account, int amount) {
// How to change account money and state without setters and public fields usage?
}
public void withdraw(Account account, int amount) {
if (account.getState() instanceof Blocked) {
throw new RuntimeException("Money could not be withdrawn. Account is blocked.");
}
if (account.getMoney() - amount <= 0) {
throw new RuntimeException("Money could not be withdrawn. Insufficient funds.");
}
// How to change account money and state without setters and public fields usage?
}
}
class Blocked implements AccountState {
public void deposit(Account account, int amount) {
// How to change account money and state without setters and public fields usage?
}
public void withdraw(Account account, int amount) {
if (account.getMoney() - amount <= 0) {
throw new RuntimeException("Money could not be withdrawn. Insufficient funds.");
}
// How to change account money and state without setters and public fields usage?
}
}
This is a very simplified example, but it well reflected my problem. Unfortunately, I couldn't found a good solution for it. All examples that I saw use either public setters or public fields. Also, I saw an example from the Refactoring to Patterns book by Joshua Kerievsky. He offers to use setters with package-level access (without access modifiers like private, public, or protected). So, we can change entity data from state classes located in the same package with the domain entity and can not do it from other packages. But this approach is using the language-specific feature - package-level access. In other languages like PHP, it wouldn't work. I'm looking for a conceptual solution.
Can anyone show a real production example solving this problem? I would really appreciate it.
Public setters (or actually setters in general regardless of access modifier) do not violate encapsulation. Encapsulation means we set up the class so only methods in the class with the variables can refer to the instance variables. In correctly encapsulated classes, callers are thus required to use these methods if they want to modify class fields.
To allow calls only from specific classes you could use reflection.
Example in Java:
How to get the caller class in Java
Example in PHP:
https://stackoverflow.com/a/6927569/724099
I would either:
Move money into AccountState (as the AccountState largely operates with money in this example)
Provide a method which manipulates Account in a way you prescribe. This may be through a method like Account#transact(String label, double amount), allowing you to manipulate the balance without exposing the member.
Remove AccountState as a redundant class, since the fields of a class are to represent the state of an object.
The second can be done through the function API as well, but do not confuse the mutability of a class member with breaking encapsulation; the purpose of encapsulation is to disallow unwanted behavior (like arbitrary math or access to internal collections). This prevents the class from entering an erroneous state.
There are many ways to solve this problem, depending on exactly what you need each state instance to do. In this specific example, I would pass the field value of money into the AccountState rather than the entire Account object.
Here is an example using an enum, but obviously that could be two separate classes with an interface instead.
public class Account {
private int balance = 0;
private AccountState currentState = AccountState.ACTIVE;
public int deposit(int amount) {
balance = currentState.deposit(balance, amount);
return balance;
}
public int withdraw(int amount) {
balance = currentState.withdraw(balance, amount);
return balance;
}
public AccountState activate() {
this.currentState = AccountState.ACTIVE;
return currentState;
}
public AccountState block() {
this.currentState = AccountState.BLOCKED;
return currentState;
}
enum AccountState {
ACTIVE {
#Override int deposit(int balance, int amount) {
return balance + amount;
}
#Override int withdraw(int balance, int amount) {
int newBalance = balance - amount;
if (newBalance >= 0) {
return newBalance;
}
throw new IllegalArgumentException("Withdrawal amount is greater than balance.");
}
},
BLOCKED {
#Override int deposit(int balance, int amount) {
throw new UnsupportedOperationException("Account is blocked.");
}
#Override int withdraw(int balance, int amount) {
throw new UnsupportedOperationException("Account is blocked.");
}
};
abstract int deposit(int balance, int amount);
abstract int withdraw(int balance, int amount);
}
}
One clue that the code in the OP will be difficult to apply OOP patterns to is that the business logic methods (deposit and withdraw) return void. It's difficult to do anything other than procedural programming with void methods. Make your methods return appropriate values and you will have an easier time composing classes that interact naturally.
Related
Let's say in a simple shopping application there are a Customer class, Seller class, and Trade class, and the code looks simply like this(to illustrate my question):
public class HelloWord {
public static void main(String[] args) {
Customer customer = new Customer();
Seller seller = new Seller();
Trade trade = new Trade(customer,seller);
trade.buy(2);
}
}
class Customer {
private ArrayList<String> itemCart = new ArrayList<String>();
private int gold = 100;
public void setGold(int amount) {
if (gold - amount >= 0) {
gold -= amount;
}
}
public int getGold() {
return gold;
}
public void add(String item) {
itemCart.add(item);
}
}
class Seller {
private ArrayList<String> itemCart = new ArrayList<String>();
private ArrayList<Integer> itemsPrice = new ArrayList<Integer>();
public int getItemPrice(int itemID) {
return itemsPrice.get(itemID);
}
public String getItemById(int itemID) {
return itemCart.get(itemID);
}
}
class Trade {
private Customer customer;
private Seller seller;
public Trade(Customer customer, Seller seller) {
this.customer = customer;
this.seller = seller;
}
public void buy(int itemID) {
if (seller.getItemPrice(itemID) <= customer.getGold()) {
customer.add(seller.getItemById(itemID));
customer.setGold(seller.getItemPrice(itemID));
} else {
System.out.println("You don't have enough money to buy this item");
}
}
}
My question is "Do the "setGold" and "add" methods expose the attruputs?" i don't want the user to be able to modify the itemCart neither the gold attribute by just call the add method or setGold on his own, but i want to be able to access them to modify the attruputs using other methods, in this case from "buy" method in Trade class.
My question in other words: "Should i be concerned if these method could be accessed from the main method or that is normal and does not violate data integrity?"
You are not getting the answer you expect because the question is a bit confusing as it is now. Reading through it carefully, you are not asking if the main method can access/change the Customer properties directly, but if the main method can use the add and setGold methods to change those properties. Also, the Seller class is just adding entropy as it's not relevant for the question.
Breaking it down:
Do the "setGold" and "add" methods expose the attruputs?
The attributes themselves are not exposed but both methods allow modifying those attributes from the outside since they are declared as public.
i don't want the user to be able to modify the itemCart neither the gold attribute buy just call the add method or set gold on his own
This is possible with your current code as both add and setGold are public. That's exactly the purpose of public.
but i want to be able to access them to modify them using other methods, in this case from "buy" method in Trade class
If you want add and setGold to be visible only to the Trade class, one option is to put Trade and Customer classes in the same package as in the following example:
com.example
shopping
|--- Customer.java
|--- Trade.java
application
|--- HelloWorld.java
And then make both methods package-private, like so:
public Customer {
// ... properties and other methods
void setGold(int amount) {
if (gold - amount >= 0) {
gold -= amount;
}
}
void add(String item) {
itemCart.add(item);
}
}
The difference to your code is that neither method contains a visibility modifier (removed the public keyword), making them package-private, thus only accessible from the same package.
With that structure and package-private methods in the Customer class, if you call the add or setGold from the main class you will get a compiler error:
add(java.lang.String) is not public in com.example.shopping.Customer;
cannot be accessed from outside package
But you can still access it from the Trade class because it's in the same package.
Short ans no, since itemCart is private, runtime caller can't access that directly.
Long answer https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.
The purpose of data encapsulation is to hide the implementation of an object by ensuring that the contents of the object are only modifiable through the interface of the object. By that definition - the Trade object inherently breaks encapsulation because of its constructor. Since you are passing in references to Customer and Seller, any invariants that the Trade object is supposed to maintain can be broken simply by the person modifying the customer or seller directly.
It's hard to know what the best alternative is without more context, but a possible fix could be rather than passing in the Customer and Seller on construction of the Trade object, passing them into the buy function. Another solution could be to attach the buy function to the Customer or Seller objects instead, getting rid of the Trade object altogether. Generally classes in OOP represent objects, and not actions (outside of certain design patterns).
The setter itself doesn't expose anything. So long as you're not exposing the exact fields (e.g. you're not doing getItemsPrice and returning an ArrayList), you're fine.
All bets are off with reflection, however. But, that's not the concern here.
I suggest you should change the setter to common form, and you can make it private.
private void set(int amount) {
this.amount = amount;
}
public boolean spend(int amount) {
if (gold - amount >= 0) {
gold -= amount;
return true;
} else {
return false;
}
}
In buy method, invoke spend().
public class ClassA_V01 {
private String name;
private int age;
// getter and setter
}
public class ClassA_V02 {
private String name;
private int age;
private int gender;
// getter and setter
}
public static void main(String[] args) {
SomeClass classA = new ClassA_V01();
classA.setName("myName);
classA.setAge(99);
performLogic(classA);
// OR
SomeClass classA = new ClassA_V02();
classA.setName("myName);
classA.setAge(99);
classA.setAge(1);
performLogic(classA);
}
public void performLogic(SomeClass classA) {
// do something
}
For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?
In my example, ClassA_V01 and ClassA_V02 are the same class except that one has more attribute "gender"
How does one implement the above such that classA can be equals to either ClassA_V01() or ClassA_V02?
"...For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?..." really this is not a criteria for strategy pattern.
Strategy pattern's intent is to identify and make family of algorithms interchangeable. If you read the pattern's documentation carefully, Strategy can be used when many related classes differ only in their behavior.
Appropriate decomposition is the key for better (extendable) design. A typical (but primitive) solution to Employee assignment, sub-classing tempEmp and permanentEmp types will put us in trouble and will not allow temp employee to become permanent in its life time (which has no meaning in real terms). This happens because we miss an important point- each employees employeeness is not different, they are all same type of employees with different pay policies. (same logic can be extended for Leave policy and so on)
This becomes simple if all types of employees have Salary computation based on same components (same state). But your question is what if TempEmployee gets only basicPay whereas PermanentEmployee gets basicPay as well as travelAllowance (additional attribute which is not present for TempEmp). This can be modeled by a combination of simple inheritance hierarchy along with strategy taking care of computation algorithm dependent upon Employee's (aka. Context) attribute (age)
public class Employee {
//name and id
private PayPackage payPackage;
private int age;
PayPackage strategy;
public double computeSalary() {
return payPackage.computePay(age);
}
//get/setPayPackage(...)
}
public abstract class PayPackage {
private double basicPay;
abstract public double computePay(int age);
protected double getBasicPay(){
return basicPay;
}
}
public class TempPayPackage extends PayPackage{
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 2000.00;
}
return getBasicPay() + veteranAllowance;
}
}
public class PermanentPayPackage extends PayPackage{
private double travelAllowance;
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 5000.00;
}
return getBasicPay() + travelAllowance + veteranAllowance;
}
}
Important thing to remember is Design patterns never work alone or as an alternative, they work hand in hand with Object oriented code and other patterns.
I am new to Spring and while learning the concepts I noticed that all the members are kept private i.e private access modifier is used.
eg.
private String car;
Is there any special reason for this?
The idea behind private members is that the class itself retains the responsibility of its internal state, instead of the calling class. Consider a banking account class. You wouldn't want a calling class to be able to access its amount directly. Instead, you would provide other methods which contain logic, based on what the calling class wants.
private int amount;
public int getAmount() {
return amount;
}
public void withdraw(int amount) {
if (this.amount - amount >= 0) {
this.amount -= amount;
}
}
public void deposit(int amount) {
this.amount += amount;
}
The above class would allow a calling class to make deposits, withdrawals and inspect the amount, while the class itself would retain responsibility over its state.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
My computer science teachers have told me that I should not be printing strings from methods such as getters and that I should be printing from the main method to the user. I was wondering if it mattered where I print from and what is the proper way to structure my code.
For example:
public class Main {
public static void main(String[] args) throws IOException {
Bank bank = new Bank(20);
System.out.println(bank.getBalance());
}
}
public class Bank {
int balance;
public Bank(int balance){
this.balance = balance;
}
public String getBalance(){
return "You have $" + this.balance;
}
}
as opposed to how my teacher says I should write it
public class Main {
public static void main(String[] args) throws IOException {
Bank bank = new Bank(20);
System.out.println("You have $" + bank.getBalance());
}
}
public class Bank{
int balance;
public Bank(int balance){
this.balance = balance;
}
public int getBalance(){
return this.balance;
}
}
Your teacher is right.
You are not really printing anything in your getters, just that you are obscuring the data types. A balance of an account (not really a bank) is presumably a numeric type (int, long) and not a String.
In general, let your methods do one thing right. By printing something in your getter and returning is okay for debugging, but not advisable in general. And that's what your teacher means.
Writing classes that have well-defined and type-safe API is useful and important especially in Java.
Your teacher is correct.
The purpose of the getBalance method is to "get" the balance in a way that other parts of your application can use it. There are lots of ways that the balance could be used, including printing it (in various places / various ways) adding it to a spreadsheet, adding it to a total, etcetera.
If you design your getBalance() method to just format and print the balance (to standard output), then all of the other things require other methods ... for each other thing.
There is a principle in software engineering known as "separation of concerns". A class (or more generally, a module) should do the things that it needs to do, and leave the other things to the caller of the classes methods. In this case, we are talking about SoC at a fine-grained level ... but the principle applies at this level too.
The version your teacher would have you write makes more sense to me. As a user of your Java classes, I prefer getting the balance as a numeric and then use it any way I wish. Presenting the data as a USD string is obviously a valid use case, but not the only one I could think of. Suppose, as a client of your class, that I'd like to know how many euros, pounds or rupees I could get with my account, then the second implementation would suit me better.
Your teacher is probably suggesting that the Bank should not be responsible for how to display the balance as a string, since different people using the bank may want to display the balance differently.
One way to deal with this is by simply keeping the bank as your professor suggests, and just format it in your own way after you get the balance number.
Second way is to make your own formatter class that formats the string in the way you want like:
public class Main2
{
public Main2() {
Bank bank = new Bank(20);
System.out.println(BalanceFormat.formatBalance(bank.getBalance()));
}
public static void main(String[] args) {
new Main2();
}
}
class Bank {
private int balance;
public Bank(int balance) {
this.balance = balance;
}
public int getBalance() {
return balance;
}
}
class BalanceFormat
{
public static String formatBalance(int balance) {
return ("Your balance is $" + balance);
}
}
The third way to do this is via callbacks, this way you tell the bank how you want it to behave while it maintains its' defaults.
public class Main
{
public Main()
{
Bank bank = new Bank(20);
System.out.println(bank.getBalanceString());
Bank bank2 = new Bank(20, (balance) -> {
return ("Your balance is: $" + balance);
});
System.out.println(bank2.getBalanceString());
}
public static void main(String[] args)
{
new Main();
}
private class Bank
{
int balance;
BalanceStringCallback bankPrintBehavior = null;
public Bank(int balance, BalanceStringCallback callback)
{
this.bankPrintBehavior = callback;
this.balance = balance;
}
public Bank(int balance)
{
this.balance = balance;
}
public int getBalance()
{
return this.balance;
}
public String getBalanceString()
{
if (bankPrintBehavior == null) {
return String.valueOf(balance);
} else {
return (bankPrintBehavior.callback(balance));
}
}
}
#FunctionalInterface
private interface BalanceStringCallback
{
abstract String callback(int balance);
}
}
There are other ways, like creating your own subclass of Bank and make it know how to format in the way you like it(Although this makes changing how one bank behaves harder, whereas the third approach of callbacks also allows you to change the behavior on the fly), but those three ways are first that popped to mind.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Property and Encapsulation
NEWB Alert!!
I am starting with Android and Java and I am starting to understand it but I am wondering why I should use getters and setters and not just public variables?
I see many people make a private variable and create a get and set method.
What is the idea here?
Its called encapsulation and the concept is central to object oriented programming. The idea is that you hide the implementation of your class and expose only the contract i.e. hide the how and only expose the what. You hide the variables by making them private and provide public setters-getters and other public methods which the clients invoke to communicate with your class. They are not tied to the actual implementation of the methods or how you store your variables.
For example, suppose you had this class where you stored a phone number as a Long object:
public class ContactInfo {
private Long phoneNo;
public Long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = phoneNo;
}
}
Since the clients of the class only see the getter/setter, you can easily change the implementation of the class/methods by switching the phone number representation to a PhoneNumber object. Clients of ContactInfo wouldn't get affected at all:
public class ContactInfo {
private PhoneNumber phoneNo;
public Long getPhoneNo() {
return phoneNo.getNumber();
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = new PhoneNumber(phoneNo);
}
}
public class PhoneNumber {
private Long number;
public PhoneNumber(Long number) {
this.number = number;
}
public Long getNumber() {
return number;
}
}
The OOP concept involved is encapsulation (google it).
Some of the advantages are: you can specify different access level for setters (mutators) and getters (accessors), for example public getter and private setter. Another advantage is that you can add another code other than changing or retrieving the value. For example, you may want to check the validity of the set value, or you want to throw exceptions or raise some events in response to changing the variable to certain value. If you implement these inside an accessor or mutators, you can also change their implementations without changing any code outside of the class.
I believe the idea is "information hiding" http://en.wikipedia.org/wiki/Information_hiding
It also serves to control the access to variables (provides an interface). For example, you can provide a getter but not a setter, so that they may be read but not written. Whereas if everything was public any thing could read and write to the variables.
Also important is any checking/validation need to set a variable. For example you have a String name that is not allowed to be empty but if it is public it could easily be forgotten and set as name = "". If you have a setter such as public boolean setName(String newName) you can check newNames length and return true or false if it passes and is set or not
The concept is called encapsulation.
What it attempts to do is to separate the inner structure of a class from its behaviour.
For example, suppose a class like this
public class Point{
private float x;
private float y;
public float getX(){
return x;
}
public float getY(){
return y;
}
public float distanceToZero2(){
return x*x + y*y
}
public float getAngle(){
//havent considered the x = 0 case.
return atan(y/x);
}
public boolean isInFirstQuad(){
return x>0 && y>0;
}
}
In this case, encapsulation hides the inner structure of the class, and exposes only the operations available to a Point. If you dont like it, you can change its inner structure and mantain its behaviour (for example, changing carthesian coordinates to polar coordinates).
Anyoune who uses this class wont care about it, he /she will be happy that they have a Point class with this functionality.
Asides the encapsulation, you can also control the value get or set to your variable in some cases. For example, you want to validate the value of an age variable which should be >=1
class Person {
private int age = Integer.MIN_VALUE;
public void setAge(int age){
if(age>=1)
this.age = age;
}
public int getAge(){
return age;
}
}