41状态模式(State Pattern)

对象状态影响对象行为:
    对象拥有不同的状态,往往会行使不同的行为...
                   
动机:
    在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
    如何在运行时根据对象的状态来透明更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
意图:
 允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。  ------《设计模式》GOF
结构图:
    
适用性:

    1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有庞大的多分支的等条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个分支放入一个独立的类中。这使得你可根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
代码实现:
    

 


  class MainApp
  {
    static void Main()
    {
      // Open a new account
      Account account = new Account("Jim Johnson");

      // Apply financial transactions
      account.Deposit(500.0);
      account.Deposit(300.0);
      account.Deposit(550.0);
      account.PayInterest();
      account.Withdraw(2000.00);
      account.Withdraw(1100.00);

      // Wait for user
      Console.Read();
    }
  }

  // "State"

  abstract class State
  {
    protected Account account;
    protected double balance;

    protected double interest;
    protected double lowerLimit;
    protected double upperLimit;

    // Properties
    public Account Account
    {
      get{ return account; }
      set{ account = value; }
    }

    public double Balance
    {
      get{ return balance; }
      set{ balance = value; }
    }

    public abstract void Deposit(double amount);
    public abstract void Withdraw(double amount);
    public abstract void PayInterest();
  }

  // "ConcreteState"

  // Account is overdrawn

  class RedState : State
  {
    double serviceFee;

    // Constructor
    public RedState(State state)
    {
      this.balance = state.Balance;
      this.account = state.Account;
      Initialize();
    }

    private void Initialize()
    {
      // Should come from a datasource
      interest = 0.0;
      lowerLimit = -100.0;
      upperLimit = 0.0;
      serviceFee = 15.00;
    }

    public override void Deposit(double amount)
    {
      balance += amount;
      StateChangeCheck();
    }

    public override void Withdraw(double amount)
    {
      amount = amount - serviceFee;
      Console.WriteLine("No funds available for withdrawal!");
    }

    public override void PayInterest()
    {
      // No interest is paid
    }

    private void StateChangeCheck()
    {
      if (balance > upperLimit)
      {
        account.State = new SilverState(this);
      }
    }
  }

  // "ConcreteState"

  // Silver is non-interest bearing state

  class SilverState : State
  {
    // Overloaded constructors

    public SilverState(State state) :
      this( state.Balance, state.Account)
    {  
    }

    public SilverState(double balance, Account account)
    {
      this.balance = balance;
      this.account = account;
      Initialize();
    }

    private void Initialize()
    {
      // Should come from a datasource
      interest = 0.0;
      lowerLimit = 0.0;
      upperLimit = 1000.0;
    }

    public override void Deposit(double amount)
    {
      balance += amount;
      StateChangeCheck();
    }

    public override void Withdraw(double amount)
    {
      balance -= amount;
      StateChangeCheck();
    }

    public override void PayInterest()
    {
      balance += interest * balance;
      StateChangeCheck();
    }

    private void StateChangeCheck()
    {
      if (balance < lowerLimit)
      {
        account.State = new RedState(this);
      }
      else if (balance > upperLimit)
      {
        account.State = new GoldState(this);
      }
    }
  }

  // "ConcreteState"

  // Interest bearing state

  class GoldState : State
  {
    // Overloaded constructors
    public GoldState(State state)
      : this(state.Balance,state.Account)
    {  
    }

    public GoldState(double balance, Account account)
    {
      this.balance = balance;
      this.account = account;
      Initialize();
    }

    private void Initialize()
    {
      // Should come from a database
      interest = 0.05;
      lowerLimit = 1000.0;
      upperLimit = 10000000.0;
    }

    public override void Deposit(double amount)
    {
      balance += amount;
      StateChangeCheck();
    }

    public override void Withdraw(double amount)
    {
      balance -= amount;
      StateChangeCheck();
    }

    public override void PayInterest()
    {
      balance += interest * balance;
      StateChangeCheck();
    }

    private void StateChangeCheck()
    {
      if (balance < 0.0)
      {
        account.State = new RedState(this);
      }
      else if (balance < lowerLimit)
      {
        account.State = new SilverState(this);
      }
    }
  }

  // "Context"

  class Account
  {
    private State state;
    private string owner;

    // Constructor
    public Account(string owner)
    {
      // New accounts are 'Silver' by default
      this.owner = owner;
      state = new SilverState(0.0, this);
    }

    // Properties
    public double Balance
    {
      get{ return state.Balance; }
    }

    public State State
    {
      get{ return state; }
      set{ state = value; }
    }

    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}\n" ,
        this.State.GetType().Name);
      Console.WriteLine("");
    }

    public void Withdraw(double amount)
    {
      state.Withdraw(amount);
      Console.WriteLine("Withdrew {0:C} --- ", amount);
      Console.WriteLine(" Balance = {0:C}", this.Balance);
      Console.WriteLine(" Status = {0}\n" ,
        this.State.GetType().Name);
    }

    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);
    }
  }

结果:
    
State模式的几个要点:
    1.State模式将所有一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
    2.为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的----即要么彻底转换过来,要么不转换。
    3.如果State对象没有实例变量,那么各个上下文可以共享 同一个State对象,从而节省对象开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中空格属于字符吗_举例说明python中空格是属于字符

python中空格属于字符吗&#xff1f;答案是肯定的&#xff0c;空格在Python中也是属于字符的。案例&#xff1a;输入一行字符&#xff0c;分别统计出其中英文字母、空格、数字和其它字符的个数。#!/usr/bin/python# -*- coding: UTF-8 -*-import strings raw_input(input a st…

【转】如何将域中的AD数据导入SharePoint

最近刚装好sharepoint2010&#xff0c;想要研究一下&#xff0c;第一件想做的事就是想把AD中的用户信息导入到SharePoint中。 那现在就来看看我是怎么操作的&#xff1a; 1.打开管理中心 sharepoint是通过“用户配置文件同步服务”来实现同步&#xff0c;所以第一步要开启这个…

Apsara Clouder专项技能认证:实现调用API接口

一.API 简介 1.API 的概念 API(Application Programming Interface应用程序编程接口)是一些预定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码或理解内部工作机制的细节 2.API 的特点 API 是一个明确定义的接口,可以为其…

第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待

一. 再谈委托 1. 委托是一个关键字为delegate的自定义类型&#xff0c;通过委托可以把方法以参数的形式传递给另外一个方法&#xff0c;实现插件式的开发模式&#xff1b; 同时调用委托的时候&#xff0c;委托所包含的所有方法都会被实现。 2. 委托的发展历史&#xff1a;new…

linux 修改 java 内存_Linux 和 Windows修改Java虚拟机内存大小

因为内存溢出问题1. Linux下直接修改%tomcat_home%/bin/catalina.sh文件在注释下紧接一行也就是脚本正文开始之前 加上Java_OPTS-server -Xms512m -Xmx1024m -XX:PermSize128m -XX:MaxPermSize512m如果报-x没有定义,则用declare -x JAVA_OPTS"-Xms512m -Xmx1024"初始…

第二节:深入剖析Thread的五大方法、数据槽、内存栅栏

一. Thread及其五大方法 Thread是.Net最早的多线程处理方式&#xff0c;它出现在.Net1.0时代&#xff0c;虽然现在已逐渐被微软所抛弃&#xff0c;微软强烈推荐使用Task(后面章节介绍)&#xff0c;但从多线程完整性的角度上来说&#xff0c;我们有必要了解下N年前多线程的是怎么…

java redis 生成唯一id_Redis在集群环境中生成唯一ID

概述设计目标&#xff1a;每秒最大生成10万个ID&#xff0c;ID单调递增且唯一。Reidis可以不需要持久化ID。要求:集群时钟不能倒退。总体思路&#xff1a;集群中每个节点预生成生成ID&#xff1b;然后与redis的已经存在的ID做比较。如果大于&#xff0c;则取节点生成的ID&#…

java await signal_【Java并发008】原理层面:ReentrantLock中 await()、signal()/signalAll()全解析...

一、前言上篇的文章中我们介绍了AQS源码中lock方法和unlock方法&#xff0c;这两个方法主要是用来解决并发中互斥的问题&#xff0c;这篇文章我们主要介绍AQS中用来解决线程同步问题的await方法、signal方法和signalAll方法&#xff0c;这几个方法主要对应的是synchronized中的…

第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案

一. Task的各种返回值-Task<TResult> PS&#xff1a; 在前面章节&#xff0c;我们介绍了Task类开启线程、线程等待、线程延续的方式&#xff0c;但我们并没有关注这些方式的返回值&#xff0c;其实他们都是有返回值的Task<TResult>&#xff0c;然后可以通过Task的…

mysql2005触发器修改成绩_创建、更改和删除触发器

创建、更改和删除触发器Creating, Altering, and Removing Triggers08/06/2017本文内容适用于&#xff1a;Applies to: SQL ServerSQL Server(所有支持的版本)SQL ServerSQL Server (all supported versions) Azure SQL 数据库Azure SQL DatabaseAzure SQL 数据库Azure SQL Dat…

第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较

一. 面向对象思想 1. 面向过程&#xff08;OP&#xff09;和面向对象&#xff08;OO&#xff09;的区别&#xff1a; (1)&#xff1a;面向过程就是排着用最简单的代码一步一步写下去&#xff0c;没有封装&#xff0c;当业务复杂的时候&#xff0c;改动就很麻烦了 (2)&#xff…

第二节:重写(new)、覆写(overwrite)、和重载(overload)

一. 重写 1. 关键字&#xff1a;new 2. 含义&#xff1a;子类继承父类中的普通方法&#xff0c;如果在子类中重写了一个和父类中完全相同的方法&#xff0c;子类中会报警告(问是否显式的隐藏父类的中的方法)&#xff0c;如果在子类中的方法前加上new关键字&#xff0c;则警告…

java 分页查询_JavaWeb之分页查询

时间&#xff1a;2016-12-11 01:411、分页的优点&#xff1a;只查询一页&#xff0c;不需要查询所有数据&#xff0c;能够提高效率。2、分页数据页面的数据都是由Servlet传递的* 当前页&#xff1a;pageCode> 如果页面没有向Servlet传递页码&#xff0c;那么Servlet默认…

第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字

一. 各类数据结构比较及其线程安全问题 1. Array(数组)&#xff1a; 分配在连续内存中,不能随意扩展&#xff0c;数组中数值类型必须是一致的。数组的声明有两种形式&#xff1a;直接定义长度&#xff0c;然后赋值&#xff1b;直接赋值。 缺点&#xff1a;插入数据慢。 优点&a…

第四节:IO、序列化和反序列化、加密解密技术

一. IO读写   这里主要包括文件的读、写、移动、复制、删除、文件夹的创建、文件夹的删除等常规操作。 注意&#xff1a;这里需要特别注意&#xff0c;对于普通的控制台程序和Web程序&#xff0c;将"相对路径"转换成"绝对路径"的方法不一致。 (1). 在w…

java mediator_java—mediator中介模式

中介者模式是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一&#xff0c;Mediator模式定义:用一个中介者对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立的改变他们之间的交互。适用性…

第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

一. 泛型诞生的背景 在介绍背景之前&#xff0c;先来看一个案例&#xff0c;要求&#xff1a;分别输出实体model1、model2、model3的id和name值,这三个实体有相同的属性名字id和name。 1 public class myUtils2 {3 //要求&#xff1a;分别输出实体model1、model2、…

第六节:反射(几种写法、好处和弊端、利用反射实现IOC)

一. 加载dll,读取相关信息 1. 加载程序集的三种方式 调用Assembly类下的三个方法&#xff1a;Load、LoadFile、LoadFrom。 1       //1.1 Load方法&#xff1a;动态默认加载当前路径下的(bin)下的dll文件,不需要后缀 2 Assembly assembly Assembly.Load(&…

第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)

一. 语法糖简介 语法糖也译为糖衣语法&#xff0c;是由英国计算机科学家彼得约翰兰达&#xff08;Peter J. Landin&#xff09;发明的一个术语&#xff0c;指计算机语言中添加的某种语法&#xff0c;这种语法对语言的功能并没有影响&#xff0c;但是更方便程序员使用。通常来说…

java不用插件播放媒体文件_java servlet不用插件上传文件:

展开全部import java.net.*;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class SaveFileServlet extends HttpServlet{FileWriter savefile;String filename null;String value null;/*** Handles a POST request*/publ…