Java 从状态类访问上下文类的私有字段
我对状态模式实现感到困惑。在这种模式下,我们应该将状态管理提取到单独的类中。乍一看,如果。。。或者…在域实体内部构造,这真的是一个强大的优势。我们可以将所有条件检查移动到状态类中,并清除域实体类 但是如何在不违反封装原则的情况下修改封装在域对象中的数据呢Java 从状态类访问上下文类的私有字段,java,design-patterns,encapsulation,state-pattern,Java,Design Patterns,Encapsulation,State Pattern,我对状态模式实现感到困惑。在这种模式下,我们应该将状态管理提取到单独的类中。乍一看,如果。。。或者…在域实体内部构造,这真的是一个强大的优势。我们可以将所有条件检查移动到状态类中,并清除域实体类 但是如何在不违反封装原则的情况下修改封装在域对象中的数据呢 例如,考虑帐户< /代码>实体。简单地说,它有两种可能的状态-活动和被阻止以及存款和取款方法 在国家模式下,我们应该把存款和取款的责任委托给国家阶级 但是我们如何修改AccountState实现中的money和state字段呢?我只看到了我有公
例如,考虑<代码>帐户< /代码>实体。简单地说,它有两种可能的状态-
活动
和被阻止
以及存款和取款方法
在国家模式下,我们应该把存款和取款的责任委托给国家阶级
但是我们如何修改AccountState
实现中的money
和state
字段呢?我只看到了我有公众支持的方式。但它违反了封装原则。通过这种方法,我还可以将私有字段更改为公共字段
代码示例:
类帐户{
私人货币;
私人帐户国家;
公共帐户(){
这是0.money=0;
this.state=new Active();
}
公共作废保证金(整笔金额){
本.状态.存款(本,金额);
}
公开作废取款(整笔金额){
本.状态.提取(本,金额);
}
public int getMoney(){
归还这笔钱;
}
公共帐户状态getState(){
返回此.state;
}
}
接口帐户状态{
公共无效存款(账户,整数金额);
公共作废取款(账户,整数金额);
}
类活动实现AccountState{
公共无效存款(账户,整数金额){
//如何在不使用设置器和公共字段的情况下更改帐户货币和状态?
}
公共作废取款(账户,整笔金额){
if(account.getState()instanceof Blocked){
抛出新的RuntimeException(“无法取款。帐户被阻止”);
}
if(account.getMoney()-amountPublic setters(或通常不考虑访问修饰符的实际setters)不要违反封装。封装意味着我们设置了类,这样只有类中带有变量的方法才能引用实例变量。在正确封装的类中,调用方需要使用这些方法才能修改类字段。Public setter(或实际上,不管访问修饰符如何,通常都是setter)不要违反封装。封装意味着我们设置了类,这样只有类中带有变量的方法才能引用实例变量。在正确封装的类中,如果调用方希望修改类字段,则需要使用这些方法。要仅允许从特定类调用,可以使用反射
Java中的示例:
PHP中的示例:
要仅允许来自特定类的调用,可以使用反射
Java中的示例:
PHP中的示例:
我想:
- 将
money
移动到AccountState
(在本例中,AccountState
主要使用money
操作)
- 提供一种按照您规定的方式操纵
账户的方法。这可以通过类似账户#交易(字符串标签,双倍金额)
的方法,允许您在不暴露会员的情况下操纵余额
- 删除AccountState作为冗余类,因为类的字段表示对象的状态
第二种方法也可以通过函数API实现,但不要将类成员的易变性与破坏封装混为一谈;封装的目的是禁止不必要的行为(如任意数学或访问内部集合)。这可以防止类进入错误状态。我会:
- 将
money
移动到AccountState
(在本例中,AccountState
主要使用money
操作)
- 提供一种按照您规定的方式操纵
账户的方法。这可以通过类似账户#交易(字符串标签,双倍金额)
的方法,允许您在不暴露会员的情况下操纵余额
- 删除AccountState作为冗余类,因为类的字段表示对象的状态
第二种方法也可以通过函数API实现,但不要将类成员的易变性与破坏封装混为一谈;封装的目的是禁止不必要的行为(如任意数学或访问内部集合)。这可以防止类进入错误状态。解决此问题的方法有很多,具体取决于每个状态实例需要执行的操作。在这个特定示例中,我将把money
的字段值传递到AccountState
中,而不是整个Account
对象中
下面是一个使用枚举的示例,但很明显,它可能是两个单独的类,并带有一个接口
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);
}
}
OP中的代码很难应用OOP模式的一个线索是业务逻辑方法(存款
和提取
)returnvoid
。除了使用void
方法进行过程编程之外,很难做任何事情。让您的方法返回适当的值,这样您就可以更轻松地组成自然交互的类。解决此问题的方法有很多,具体取决于您需要每个状态实例执行的操作在这个特定的例子中,我将把money
的字段值传递到AccountState
而不是整个Account
对象中
下面是一个使用