设计模式之十 --- 状态(State)模式

【1】基本概念

          状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

【2】简单分析

         我们先来看下该设计模式的UML的结构图

【3】如何用Java语言实现该设计模式

本篇文章以一个贴近现实生活的例子来展示如何使用该设计模式,以方便大家尽快的掌握状态设计模式。例子:如某人去银行新开一个账户,该账户可以用来存钱或者取钱,我们可以以账户中的总资金来判断显示某用户账户的状态:红色状态(RedState),银色状态(SliverState),金色状态GoldState)。其实就好比银行中根据我们存储卡中的资金来给客户某种身份的识别,例如普通用户,VIP客户,公司客户....等等。

我们先看下该实例Demo的结构图:

3.1 State.java 源码:

 
  1. package com.andyidea.patterns.concretestate;

  2.  
  3. import com.andyidea.patterns.context.Account;

  4.  
  5. /**

  6. * State类,抽象状态类,定义一个接口以封装

  7. * 与Context的一个特定状态相关的行为。

  8. * @author Andy

  9. *

  10. */

  11. public abstract class State {

  12.  
  13. protected Account account;

  14. protected double balance;

  15.  
  16. protected double interest;

  17. protected double lowerLimit;

  18. protected double upperLimit;

  19.  
  20. //-------------Properties------------------//

  21. public Account getAccount() {

  22. return account;

  23. }

  24. public void setAccount(Account account) {

  25. this.account = account;

  26. }

  27.  
  28. public double getBalance() {

  29. return balance;

  30. }

  31. public void setBalance(double balance) {

  32. this.balance = balance;

  33. }

  34. //------------------------------------------//

  35.  
  36. /**存入金额*/

  37. public abstract void deposit(double amount);

  38. /**支出金额*/

  39. public abstract void withdraw(double amount);

  40. /**利息*/

  41. public abstract void payInterest();

  42.  
  43. }

3.2  RedState.java源码:

 
  1. package com.andyidea.patterns.concretestate;

  2.  
  3.  
  4. /**

  5. * 用户账户状态:RedState

  6. * @author Andy

  7. * ConcreteState类,具体状态,每一个子类实现一个与

  8. * Context的一个状态相关的行为。

  9. */

  10. public class RedState extends State {

  11.  
  12. private double serviceFee;

  13.  
  14. public RedState(State state) {

  15. this.balance = state.getBalance();

  16. this.account = state.getAccount();

  17. initialize();

  18. }

  19.  
  20. /** 模拟初始化基础数据*/

  21. private void initialize() {

  22. interest = 0.0;

  23. lowerLimit = -100.0;

  24. upperLimit = 0.0;

  25. serviceFee = 15.00;

  26. }

  27.  
  28. @Override

  29. public void deposit(double amount) {

  30. balance += amount;

  31. stateChangeCheck();

  32. }

  33.  
  34. @Override

  35. public void withdraw(double amount) {

  36. amount = amount - serviceFee;

  37. System.out.println("No funds available for withdrawal!");

  38. }

  39.  
  40. @Override

  41. public void payInterest() {

  42. // No interest is paid

  43. }

  44.  
  45. /** 状态检测 */

  46. private void stateChangeCheck() {

  47. if (balance > upperLimit) {

  48. account.setState(new SilverState(this));

  49. }

  50. }

  51.  
  52. }

SliverState.java源码:

 
  1. package com.andyidea.patterns.concretestate;

  2.  
  3. import com.andyidea.patterns.context.Account;

  4.  
  5. /**

  6. * 用户账户状态:SilverState

  7. * @author Andy

  8. * ConcreteState类,具体状态,每一个子类实现一个与

  9. * Context的一个状态相关的行为。

  10. */

  11. public class SilverState extends State {

  12.  
  13. public SilverState(State state){

  14. this(state.balance,state.account);

  15. }

  16.  
  17. public SilverState(double balance, Account account){

  18. this.balance = balance;

  19. this.account = account;

  20. initialize();

  21. }

  22.  
  23. /** 模拟初始化基础数据*/

  24. private void initialize(){

  25. interest = 0.0;

  26. lowerLimit = 0.0;

  27. upperLimit = 1000.0;

  28. }

  29.  
  30. @Override

  31. public void deposit(double amount) {

  32. balance += amount;

  33. stateChangeCheck();

  34. }

  35.  
  36. @Override

  37. public void withdraw(double amount) {

  38. balance -= amount;

  39. stateChangeCheck();

  40. }

  41.  
  42. @Override

  43. public void payInterest() {

  44. balance += interest * balance;

  45. stateChangeCheck();

  46. }

  47.  
  48. /** 状态检测 */

  49. private void stateChangeCheck(){

  50. if (balance < lowerLimit){

  51. account.setState(new RedState(this));

  52. }

  53. else if (balance > upperLimit){

  54. account.setState(new GoldState(this));

  55. }

  56. }

  57.  
  58. }

GoldState.java源码:

 
  1. package com.andyidea.patterns.concretestate;

  2.  
  3. import com.andyidea.patterns.context.Account;

  4.  
  5. /**

  6. * 用户账户状态:GoldState

  7. * @author Andy

  8. * ConcreteState类,具体状态,每一个子类实现一个与

  9. * Context的一个状态相关的行为。

  10. */

  11. public class GoldState extends State {

  12.  
  13. public GoldState(State state){

  14. this(state.balance, state.account);

  15. }

  16.  
  17. public GoldState(double balance, Account account){

  18. this.balance = balance;

  19. this.account = account;

  20. initialize();

  21. }

  22.  
  23. /** 模拟初始化基础数据*/

  24. private void initialize(){

  25. interest = 0.05;

  26. lowerLimit = 1000.0;

  27. upperLimit = 10000000.0;

  28. }

  29.  
  30. @Override

  31. public void deposit(double amount) {

  32. balance += amount;

  33. stateChangeCheck();

  34. }

  35.  
  36. @Override

  37. public void withdraw(double amount) {

  38. balance -= amount;

  39. stateChangeCheck();

  40. }

  41.  
  42. @Override

  43. public void payInterest() {

  44. balance += interest * balance;

  45. stateChangeCheck();

  46. }

  47.  
  48. /** 状态检测 */

  49. private void stateChangeCheck() {

  50. if (balance < 0.0) {

  51. account.setState(new RedState(this));

  52. } else if (balance < lowerLimit) {

  53. account.setState(new SilverState(this));

  54. }

  55. }

  56.  
  57. }

3.3 Account.java类源码:

 
  1. package com.andyidea.patterns.context;

  2.  
  3. import com.andyidea.patterns.concretestate.SilverState;

  4. import com.andyidea.patterns.concretestate.State;

  5.  
  6. /**

  7. * Context类,维护一个ConcreteState子类的实例

  8. * 这个实例定义当前的状态。

  9. * @author Andy

  10. *

  11. */

  12. public class Account {

  13.  
  14. private State state;

  15. private String owner;

  16.  
  17. public Account(String owner){

  18. // 新开账户默认为 Silver状态

  19. this.owner = owner;

  20. this.state = new SilverState(0.0, this);

  21. }

  22.  
  23. public State getState() {

  24. return state;

  25. }

  26.  
  27. public void setState(State state) {

  28. this.state = state;

  29. }

  30.  
  31. public void deposit(double amount) {

  32. state.deposit(amount);

  33. System.out.println(owner + " Deposited " + amount);

  34. System.out.println(owner + " Balance = " + state.getBalance());

  35. System.out.println("Status = " + state.getClass().getSimpleName());

  36. System.out.println("==============================================");

  37. }

  38.  
  39. public void withdraw(double amount){

  40. state.withdraw(amount);

  41. System.out.println(owner + " Withdrew " + amount);

  42. System.out.println(owner + " Balance = " + state.getBalance());

  43. System.out.println("Status = " + state.getClass().getSimpleName());

  44. System.out.println("==============================================");

  45. }

  46.  
  47. public void payInterest(){

  48. state.payInterest();

  49. System.out.println(owner + " Interest Paid ");

  50. System.out.println(owner + " Balance = " + state.getBalance());

  51. System.out.println("Status = " + state.getClass().getSimpleName());

  52. System.out.println("==============================================");

  53. }

  54.  
  55. }

3.4 客户端测试类 StateClient.java 类源码:

 
  1. package com.andyidea.patterns;

  2.  
  3. import com.andyidea.patterns.context.Account;

  4.  
  5. public class StateClient {

  6.  
  7. public static void main(String[] args) {

  8. // 新开一个银行账户

  9. Account account = new Account("Andy.Chen");

  10.  
  11. // 存取款等系列操作

  12. account.deposit(500.0);

  13. account.deposit(300.0);

  14. account.deposit(550.0);

  15. account.payInterest();

  16. account.withdraw(2000.00);

  17. account.withdraw(1100.00);

  18. }

  19.  
  20. }

【4】下面我们来看下程序运行的结果:

 
  1. Andy.Chen Deposited 500.0

  2. Andy.Chen Balance = 500.0

  3. Status = SilverState

  4. ==============================================

  5. Andy.Chen Deposited 300.0

  6. Andy.Chen Balance = 800.0

  7. Status = SilverState

  8. ==============================================

  9. Andy.Chen Deposited 550.0

  10. Andy.Chen Balance = 1350.0

  11. Status = GoldState

  12. ==============================================

  13. Andy.Chen Interest Paid

  14. Andy.Chen Balance = 1417.5

  15. Status = GoldState

  16. ==============================================

  17. Andy.Chen Withdrew 2000.0

  18. Andy.Chen Balance = -582.5

  19. Status = RedState

  20. ==============================================

  21. No funds available for withdrawal!

  22. Andy.Chen Withdrew 1100.0

  23. Andy.Chen Balance = -582.5

  24. Status = RedState

  25. ==============================================

【5】总结:

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

本文为 Andy.Chen 原创,欢迎大家继续关注Me的博文,欢迎大家转载,谢谢!

https://blog.csdn.net/cjjky/article/details/7585207

猜你喜欢

转载自blog.csdn.net/varyall/article/details/82734897
今日推荐