- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个银行账户程序。每个帐户都可以处于初始状态或受信任帐户状态(当前)。将来可能会添加新的状态。如果它处于初始状态,则不支付利息。但是如果是Trusted Account State,则支付9%的利息。
以下代码有效。但是 ChangeState() 方法中存在紧密耦合。 InitialAccountState
需要知道 TrustedAccountedState
的存在。如果我们添加一个名为 VeteranAccountedState
的新状态,则 ChangeState() 方法需要在 InitialAccountState
类中重写。
减少这种耦合的最佳 .Net 4.0 方法是什么?
状态模式
The state pattern allows a object's state to change at any given moment which actually alters its behavior.
当状态变化的顺序被预定义时,耦合在状态模式中不是问题。例如,交通灯总是从绿—黄—红变化。在这种情况下,耦合不是问题——Green 确信在下一步中它始终是 Yellow 状态。引用Analysis Of State Machine Pattern
抽象状态
abstract class AccountState
{
// Properties
public BankAccount Account { get; set; }
public double Balance { get; set; }
protected double interest;
protected double lowerLimit;
protected double upperLimit;
public abstract void Deposit(double amount);
public abstract void PayInterest();
}
混凝土
class InitialAccountState : AccountState
{
public InitialAccountState(AccountState state) :this(state.Balance, state.Account)
{
}
public InitialAccountState(double balance, BankAccount account)
{
this.Balance = balance;
this.Account = account;
Initialize();
}
private void Initialize()
{
lowerLimit = 0.0;
upperLimit = 1000.0;
}
public override void Deposit(double amount)
{
Balance += amount;
ChangeState();
}
public override void PayInterest()
{
throw new Exception("No Interest Allowed");
}
private void ChangeState()
{
if (Balance > upperLimit)
{
Account.State = new TrustedAccountedState(this);
}
}
}
class TrustedAccountedState : AccountState
{
public TrustedAccountedState(AccountState state): this(state.Balance, state.Account)
{
}
public TrustedAccountedState(double balance, BankAccount account)
{
this.Balance = balance;
this.Account = account;
Initialize();
}
private void Initialize()
{
interest = 0.05;
lowerLimit = 1000.0;
upperLimit = 10000000.0;
}
public override void Deposit(double amount)
{
Balance += amount;
ChangeState();
}
public override void PayInterest()
{
Balance += interest * Balance;
ChangeState();
}
private void ChangeState()
{
if (Balance < lowerLimit)
{
Account.State = new InitialAccountState(this);
}
}
}
语境
class BankAccount
{
// Properties
public AccountState State { get; set; }
public double Balance
{
get { return State.Balance; }
}
// Constructor
public BankAccount(string owner)
{
this.State = new InitialAccountState(0.0, this);
}
public void Deposit(double amount)
{
State.Deposit(amount);
Console.WriteLine("Deposited {0:C} --- ", amount);
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}", this.State.GetType().Name);
Console.WriteLine("");
}
public void PayInterest()
{
State.PayInterest();
Console.WriteLine("INTEREST PAID --- ");
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}\n", this.State.GetType().Name);
}
}
客户
class Program
{
static void Main(string[] args)
{
BankAccount account = new BankAccount("Jim Johnson");
account.Deposit(500.0);
account.Deposit(300.0);
account.Deposit(550.0);
account.PayInterest();
Console.ReadKey();
}
}
引用文献
最佳答案
我会将状态更改重构为另一个类,例如服务类,其职责是了解如何更改状态,从而反转依赖关系并消除状态之间的紧密耦合。所以我会更改抽象类,以便可以访问 protected 属性。
abstract class AccountState
{
// Properties
public BankAccount Account { get; set; }
public double Balance { get; set; }
internal double interest;
internal double lowerLimit;
internal double upperLimit;
public abstract void Deposit(double amount);
public abstract void PayInterest();
}
添加一个 StateChanger 类...
public class StateChanger(){
public AccountState ChangeState(AccountState state){
if((state is InitialAccountState) && (state.Balance > state.upperLimit)){
return new TrustedAccountedState(state);
}
if((state is TrustedAccountedState) && (state.Balance < state.lowerLimit))
{
return new InitialAccountState(state);
}
return state;
}
}
从 AccountState 类中删除依赖项
class InitialAccountState : AccountState
{
public InitialAccountState(AccountState state) :this(state.Balance, state.Account)
{
}
public InitialAccountState(double balance, BankAccount account)
{
this.Balance = balance;
this.Account = account;
Initialize();
}
private void Initialize()
{
lowerLimit = 0.0;
upperLimit = 1000.0;
}
public override void Deposit(double amount)
{
Balance += amount;
}
public override void PayInterest()
{
throw new Exception("No Interest Allowed");
}
}
class TrustedAccountedState : AccountState
{
public TrustedAccountedState(AccountState state): this(state.Balance, state.Account)
{
}
public TrustedAccountedState(double balance, BankAccount account)
{
this.Balance = balance;
this.Account = account;
Initialize();
}
private void Initialize()
{
interest = 0.05;
lowerLimit = 1000.0;
upperLimit = 10000000.0;
}
public override void Deposit(double amount)
{
Balance += amount;
}
public override void PayInterest()
{
Balance += interest * Balance;
}
}
然后你的 BackAccount 类就像一个 Controller ,它看起来像
class BankAccount
{
// Properties
public AccountState State { get; set; }
private StateChanger stateChanger;
public double Balance
{
get { return State.Balance; }
}
// Constructor
public BankAccount(string owner,StateChanger stateChanger)
{
this.State = new InitialAccountState(0.0, this);
this.stateChanger = stateChanger;
}
public void Deposit(double amount)
{
State.Deposit(amount);
State = stateChanger.ChangeState(State);
Console.WriteLine("Deposited {0:C} --- ", amount);
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}", this.State.GetType().Name);
Console.WriteLine("");
}
public void PayInterest()
{
State.PayInterest();
State = stateChanger.ChangeState(State);
Console.WriteLine("INTEREST PAID --- ");
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}\n", this.State.GetType().Name);
}
}
主要是
class Program
{
static void Main(string[] args)
{
StateChanger stateChanger = new StateChanger();
BankAccount account = new BankAccount("Jim Johnson",stateChanger);
account.Deposit(500.0);
account.Deposit(300.0);
account.Deposit(550.0);
account.PayInterest();
Console.ReadKey();
}
}
通过分离管理状态的关注点,AccountState 类彼此分离,现在如果您需要添加更多状态,只需更新 1 个类。然后,AccountState 类将不需要保持状态,而只是定义行为,即如果您的帐户处于给定状态,Deposit 或 PayInterest 应该如何表现。您仍然可以在 statechanger 类中使用规范模式。
关于c# - 减少状态模式中的耦合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21332730/
Law of Demeter表示你应该只与你直接了解的对象交谈。也就是说,不要执行方法链接来与其他对象通信。当您这样做时,您正在与中间对象不恰本地建立不正确的链接coupling您的代码到其他代码。
我已经实现了一个 CodeService,它将从代码表中检索国家/地区列表。 在我的 ShippingService 中,我想检查订单是否运送到某个国家/地区。 在这种情况下,我应该使用 CodeSe
虽然这个论坛上有很多包含耦合和内聚示例的好示例,但我正在努力将其完全应用到我的代码中。我可以识别代码中可能需要更改的部分。是否有任何 Java 专家能够查看我的代码并向我解释哪些方面是好的和坏的。我根
我有一个创建新对象 Student 并将其添加到数组列表 studentRegister 的方法: public void addStudent(String name, String age) {
在高耦合环境中,更改一个模块会影响另一个模块。好的,但我看不出这怎么可能(除了更改方法签名或返回类型)? 好吧,如果我改变一个类,那么它只能在以下情况下破坏其他类中的代码: 如果我突然改变了一个方法的
问题描述: 我正在一个项目中,以采用现有的JavaScript脚本并对其进行修改以支持异步加载。如果您不了解异步或延迟加载脚本,但想了解更多信息read this。 main.js脚本要做的第一件事之
我正在编写一个模拟,需要一些关于设计的提示。基本思想是生成给定随机过程的数据,然后将其用于各种计算。例如对于 1 次迭代: 进程 1 -> 为源 1 生成数据:x1 进程 2 -> 为源 1 生成数据
给定两个字符串,S1 和 S2。给定的计分方案包括空位罚分、不匹配分数和匹配分数。 找到与 S2 最匹配的 S1。 我的想法是列出所有可能的S1,然后与S2一一匹配。使用暴力列出所有可能的 S1。然后
我尝试使用 ctypes.CDLL 类 (Linux) 在 Python 中加载 C 共享库 .so。这是 link告诉我我做了什么。正如我看到的文档,它说 CDLL 类假定函数返回 int 类型。我
目录 什么是耦合性 什么是程序间的耦合 如何解耦 工厂模式解耦 案例 原因就是: 解决思路:
我尝试使用 Matlab 函数 Pdepe ( https://www.mathworks.com/help/matlab/ref/pdepe.html ) 求解平流扩散 react 问题的一维耦合偏
如何处理高级 C++ 应用程序中的耦合? 我们可以使用(例如)Witty 编写的 web 应用程序的完成代码,并用它制作控制台应用程序吗? ...或者将其更改为使用 Qt 制作的带有 GUI 的桌面应
假设我们有类: class Post def save # implementation end def self.find(id) #implementation e
简介 我正在尝试使用接口(interface)、抽象类和泛型在 Java 中创建一个相当复杂的结构。由于没有使用泛型的经验,在创建良好的 OOP 设计方面只有一般经验,这开始证明是一个相当大的挑战。
考虑 Windows 资源管理器(或 regedit 或类似工具)。左侧是 TreeView ,右侧是 ListView 。在我所知道的所有情况下,右 View 的内容都反射(reflect)了左 P
我有一个耦合代码(fortran 和 c++),我现在在 python 中调用。 main.exe 工作正常,但是当我在 python 中调用耦合版本时,出现段错误(核心转储)错误。我确定了出现问题的
我正在尝试编写 CMakeLists.txt 以耦合一个简单的 FORTRAN 程序,该程序使用 iso_c_binding 调用 C++ 函数。当我使用 gfortran 作为 FORTRAN 编译
我们将 NHibernate 用于 ORM,在程序的初始化阶段,我们需要从数据库中加载某个类 T 的许多实例。 在我们的应用程序中,提取所有这些实例的以下代码需要很长时间: public IList
我是一名优秀的程序员,十分优秀!