事务的状态(状态模式)

【0】README
0.1)本文部分文字描述转自 “head first设计模式”,旨在学习  事务的状态(状态模式) 的基础知识;

【1】应用场景一
1.1)还记得成都市各大高校内的米源自动售卖机吗?售卖机的主要制造商发现,只要把CPU 放入机器,可以提高销量。于是乎,它们提供了一幅自动售卖机的状态图给我们,希望我们用java 帮他实现,且代码富有弹性易于扩展(下面以米源糖果售卖机为例给出状态图);

  • step1)米源售卖机实现
  • public class CandyMachine {
    	private final static int SOLD_OUT = 0; // 售罄状态
    	private final static int NO_QUARTER = 1; // 无币状态,QUARTER==25美分==币
    	private final static int HAS_QUARTER = 2; // 有币状态
    	private final static int SOLD = 3; // 售卖状态
    	private int state = SOLD_OUT;
    	private int count = 0;
    	
    	public CandyMachine(int count) {
    		this.count = count;
    		if(count > 0) {
    			this.state = NO_QUARTER;
    		}
    	}
    	
    	public void insertQuarter() { // client投币请求
    		if(state == HAS_QUARTER) {
    			System.out.println("you can't insert another quarter.");
    		} else if(state == NO_QUARTER) {
    			System.out.println("you insert a quarter.");
    			state = HAS_QUARTER;
    		} else if(state == SOLD_OUT) {
    			System.out.println("you can't insert a quarter for the machine is sold out.");
    		} else if(state == SOLD) {
    			System.out.println("please wait, we're already gibing you a candy.");
    		}
    	}
    	
    	public void ejectQuarter() { // client请求退钱
    		if(state == HAS_QUARTER) {
    			System.out.println("quarter returned.");
    			state = NO_QUARTER;
    		} else if(state == NO_QUARTER) {
    			System.out.println("you haven't inserted a quarter.");
    		} else if(state == SOLD_OUT) {
    			System.out.println("you can't eject for you haven't inserted a quarter yet.");
    		} else if(state == SOLD) {
    			System.out.println("sorry, you already trune the crank.");
    		}
    	}
    	
    	public void turnCrank() { // client转动曲柄动作
    		if(state == HAS_QUARTER) {
    			System.out.println("you turned, please wait....");
    			state = SOLD;
    			dispense();
    		} else if(state == NO_QUARTER) {
    			System.out.println("you turned but there is no quarter.");
    		} else if(state == SOLD_OUT) {
    			System.out.println("you truned but there's no candy.");
    		} else if(state == SOLD) {
    			System.out.println("turning twice doesn't get you another candy.");
    		}
    	}
    	
    	private void dispense() { // 分发糖果
    		if(state == HAS_QUARTER) {
    			System.out.println("no candy dispensed.");
    		} else if(state == NO_QUARTER) {
    			System.out.println("you need to insert a quarter first.");
    		} else if(state == SOLD_OUT) {
    			System.out.println("no candy dispensed.");
    		} else if(state == SOLD) {
    			System.out.println("a candy comes rolling out the slot.");
    			count--;
    			if(count == 0) {
    				System.out.println("Oops, there's no candy.");
    				state = SOLD_OUT;
    			} else {
    				state = NO_QUARTER;
    			}
    		}
    	}
    
    	@Override
    	public String toString() {
    		String state_str = null;
    		
    		switch (state) {
    		case SOLD_OUT: state_str = "SOLD_OUT"; break;
    		case SOLD: state_str = "SOLD"; break;
    		case NO_QUARTER: state_str = "NO_QUARTER"; break;
    		case HAS_QUARTER: state_str = "HAS_QUARTER"; break;
    		}
    		return "=== I own " + count + " candies, and stay in " + state_str + " state. ===";
    	}
    }
  • step2)测试用例
  • public class CandyMachineTest {
    	public static void main(String[] args) {
    		CandyMachine cm = new CandyMachine(5);
    		System.out.println(cm);
    		
    		System.out.println("====== 1st test: ======");
    		cm.insertQuarter();
    		cm.turnCrank();
    		System.out.println(cm);
    		
    		System.out.println("====== 2nd test: ======");
    		cm.insertQuarter();
    		cm.ejectQuarter();//要求售卖机退钱
    		cm.ejectQuarter();//要求售卖机第二次退钱
    		
    		System.out.println("====== 3rd test: ======");
    		cm.insertQuarter();
    		cm.ejectQuarter();
    		cm.turnCrank();// 请求退钱后,不应该得到糖果
    		System.out.println(cm);
    	}
    }
  • step3)打印结果
  • === I own 5 candies, and stay in NO_QUARTER state. ===
    ====== 1st test: ======
    you insert a quarter.
    you turned, please wait....
    a candy comes rolling out the slot.
    === I own 4 candies, and stay in NO_QUARTER state. ===
    ====== 2nd test: ======
    you insert a quarter.
    quarter returned.
    you haven't inserted a quarter.
    ====== 3rd test: ======
    you insert a quarter.
    quarter returned.
    you turned but there is no quarter.
    === I own 4 candies, and stay in NO_QUARTER state. ===
【2】应用场景二(新的需求: 当曲柄被转动时,有10%的几率掉下来的是两个糖果,即有10%的可能性买一送一)
2.1)新需求下的米源售卖机实现 (for downloading, please visit  https://github.com/pacosonTang/HeadFirstDesignPattern/tree/master/state_pattern_10/chapter10_1
  • step1)定义一个状态接口(State),在这个接口内,售卖机的每个动作有一个对应方法;
  • public abstract class State {
    	protected String name;
    	public abstract void insertQuarter();
    	public abstract void ejectQuarter();
    	public abstract void trunCrank();
    	public abstract void dispense();
    	
    	public String getName() {
    		return name;
    	}
    }
  • step2)创建该状态接口的子类,实现售卖机的相应方法;
  • // 售罄状态
    public class SoldOutState extends State {
    	CandyMachine machine;
    	
    	public SoldOutState(CandyMachine machine) {
    		super.name = "SoldOutState";
    		this.machine = machine;
    	}
    
    	@Override
    	public void insertQuarter() {
    		System.out.println("you can't insert a quarter for there's no candies.");		
    	}
    
    	@Override
    	public void ejectQuarter() {
    		System.out.println("you have not inserted a quarter.");
    	}
    
    	@Override
    	public void trunCrank() {
    		System.out.println("you turned but there is no quarter.");
    	}
    
    	@Override
    	public void dispense() {
    		System.out.println("you need to insert a quarter first.");		
    	}
    
    }
    public class NoQuarterState extends State {
    	CandyMachine machine;
    	
    	public NoQuarterState(CandyMachine machine) {
    		super.name = "NoQuarterState";
    		this.machine = machine;
    	}
    
    	@Override
    	public void insertQuarter() {
    		System.out.println("you insert a quatter.");
    		machine.setState(machine.getHasQuarterState());
    	}
    
    	@Override
    	public void ejectQuarter() {
    		if(machine.getState() == machine.getHasQuarterState()) {
    			System.out.println("returned a quarter.");
    			machine.setState(machine.getNoQuarterState());
    		} else {
    			System.out.println("you have not inserted a quarter.");
    		}
    	}
    
    	@Override
    	public void trunCrank() {
    		System.out.println("you turned but there is no quarter.");
    	}
    
    	@Override
    	public void dispense() {
    		System.out.println("you need to insert a quarter first.");		
    	}
    }
    // 有币状态
    public class HasQuarterState extends State {
    	Random random = new Random();
    	CandyMachine machine;
    	
    	public HasQuarterState(CandyMachine machine) {
    		super.name = "HasQuarterState"; 
    		this.machine = machine;
    	}
    
    	@Override
    	public void insertQuarter() {
    		System.out.println("you can't insert another quarter.");
    	}
    
    	@Override
    	public void ejectQuarter() { // client退钱请求
    		System.out.println("quarter returned.");
    		machine.setState(machine.getNoQuarterState());
    	}
    
    	@Override
    	public void trunCrank() { // 有币状态下,进行几率性中奖测试
    		System.out.println("you turned , please waiting......");
    		int winner = random.nextInt(5);
    		System.out.println("\nrandom winner == " + winner);
    		if(winner == 2 && machine.getCount() > 1) {
    			machine.setState(machine.getWinnerState());
    		} else {
    			machine.setState(machine.getSoldState());
    		}
    	}
    
    	@Override
    	public void dispense() {
    		System.out.println("no candies dispensed.");		
    	}
    }
    
    // 售卖状态
    public class SoldState extends State {
    	CandyMachine machine;
    	
    	
    	public SoldState(CandyMachine machine) {
    		super.name = "SoldState";
    		this.machine = machine;
    	}
    
    	@Override
    	public void insertQuarter() {		
    		System.out.println("please wait, we're already giving you a candy.");		
    	}
    
    	@Override
    	public void ejectQuarter() {
    		System.out.println("sorry, you've already turned the crank.");
    	}
    
    	@Override
    	public void trunCrank() {
    		System.out.println("turning twice doesn't get you another candy.");
    	}
    
    	@Override
    	public void dispense() {
    		machine.releaseBall();
    		if(machine.getCount() > 0) {
    			machine.setState(machine.getNoQuarterState());
    		} else {
    			machine.setState(machine.getSoldOutState());
    		}
    	}
    }
  • // 中奖状态
    public class WinnerState extends State {
    	CandyMachine machine;
    	
    	public WinnerState(CandyMachine machine) {
    		this.machine = machine;
    	}
    
    	@Override
    	public void insertQuarter() {
    		System.out.println("error.");
    	}
    
    	@Override
    	public void ejectQuarter() { // client退钱请求
    		System.out.println("error.");
    	}
    
    	@Override
    	public void trunCrank() {
    		System.out.println("error.");
    	}
    
    	@Override
    	public void dispense() {
    		System.out.println("you're a winner. you get 2 candies for your quarter.");
    		machine.releaseBall();
    		if(machine.getCount() == 0) {
    			machine.setState(machine.getSoldOutState());
    		} else {
    			machine.releaseBall();
    			if(machine.getCount() > 0) {
    				machine.setState(machine.getNoQuarterState());
    			} else {
    				System.out.println("Oops, out of candies.");
    				machine.setState(machine.getSoldOutState());
    			}
    		}
    	}
    }
  • step3)将动作委托到状态类(构造米源糖果售卖机);
  • public class CandyMachine {
    	private State winnerState; //中奖状态
    	private State soldOutState; // 售罄状态
    	private State noQuarterState; // 无币状态,QUARTER==25美分==币
    	private State hasQuarterState; // 有币状态
    	private State soldState; // 售卖状态
    	private State state;
    	private int count = 0;
    	
    	public CandyMachine(int count) {
    		soldOutState = new SoldOutState(this);
    		soldState = new SoldState(this);
    		hasQuarterState = new HasQuarterState(this);
    		noQuarterState = new NoQuarterState(this);
    		winnerState = new WinnerState(this);
    		state = soldOutState;
    		
    		this.count = count;
    		if(count > 0) {
    			state = noQuarterState;
    		}
    	}
    	
    	public void insertQuarter() { // client投币请求
    		state.insertQuarter();
    	}
    	
    	public void ejectQuarter() { // client请求退钱
    		state.ejectQuarter();
    	}
    	
    	public void turnCrank() { // client转动曲柄动作
    		state.trunCrank();
    		state.dispense();
    	}
    	
    	public void releaseBall() { // 释放糖果
    		System.out.println("a candy comes rolling out the slot....");
    		if(count != 0) {
    			count--;
    		}
    	}
    	
    	public State getState() {
    		return state;
    	}
    
    	public void setState(State state) {
    		this.state = state;
    	}
    	
    	public State getSoldOutState() {
    		return soldOutState;
    	}
    
    	public void setSoldOutState(State soldOutState) {
    		this.soldOutState = soldOutState;
    	}
    
    	public State getSoldState() {
    		return soldState;
    	}
    
    	public void setSoldState(State soldState) {
    		this.soldState = soldState;
    	}
    
    	public State getHasQuarterState() {
    		return hasQuarterState;
    	}
    
    	public void setHasQuarterState(State hasQuarterState) {
    		this.hasQuarterState = hasQuarterState;
    	}
    
    	public State getNoQuarterState() {
    		return noQuarterState;
    	}
    
    	public void setNoQuarterState(State noQuarterState) {
    		this.noQuarterState = noQuarterState;
    	}
    
    	public int getCount() {
    		return count;
    	}
    
    	public void setCount(int count) {
    		this.count = count;
    	}
    	public State getWinnerState() {
    		return winnerState;
    	}
    
    	public void setWinnerState(State winner) {
    		this.winnerState = winner;
    	}	
    	
    	@Override  
        public String toString() {  
            String state_str = null;  
              
            switch (state.getName()) {  
            case "SoldOutState": state_str = "SOLD_OUT"; break;  
            case "SoldState": state_str = "SOLD"; break;  
            case "NoQuarterState": state_str = "NO_QUARTER"; break;  
            case "HasQuarterState": state_str = "HAS_QUARTER"; break;  
            }  
            return "=== I own " + count + " candies, and stay in " + state_str + " state. ===";  
        }  
    }
    step4)测试用例
  • public class CandyMachineTest {
    	public static void main(String[] args) {
    		CandyMachine cm = new CandyMachine(50);
    		System.out.println(cm);
    		
    		System.out.println("====== init state ======");
    		System.out.println(cm);
    		
    		// 第一次测试
    		cm.insertQuarter();
    		cm.turnCrank();
    		System.out.println(cm);
    				
    		// 第二次测试
    		cm.turnCrank();
    		System.out.println(cm);
    		
    		// 第3次测试: 在为投币的情况下退币请求
    		cm.ejectQuarter();
    		System.out.println(cm);
    		
    		System.out.println("\n\n ====== 下面进入循环测试(中奖)随机数==2表示中奖 ======");
    		for (int i = 0; i < 5; i++) {
    			cm.insertQuarter();
    			cm.turnCrank();
    			System.out.println(cm);
    		}
    	}
    }
  • step5)打印结果
  • === I own 50 candies, and stay in NO_QUARTER state. ===
    ====== init state ======
    === I own 50 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 0
    a candy comes rolling out the slot....
    === I own 49 candies, and stay in NO_QUARTER state. ===
    you turned but there is no quarter.
    you need to insert a quarter first.
    === I own 49 candies, and stay in NO_QUARTER state. ===
    you have not inserted a quarter.
    === I own 49 candies, and stay in NO_QUARTER state. ===
    
    
     ====== 下面进入循环测试(中奖,为了演示方便,我这里的中奖率为20%,且 <span style="font-family: Arial, Helvetica, sans-serif;">随机数==2表示中奖</span><span style="font-family: Arial, Helvetica, sans-serif;">) ======</span>
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 2
    you're a winner. you get 2 candies for your quarter.
    a candy comes rolling out the slot....
    a candy comes rolling out the slot....
    === I own 47 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 4
    a candy comes rolling out the slot....
    === I own 46 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 4
    a candy comes rolling out the slot....
    === I own 45 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 2
    you're a winner. you get 2 candies for your quarter.
    a candy comes rolling out the slot....
    a candy comes rolling out the slot....
    === I own 43 candies, and stay in NO_QUARTER state. ===
    you insert a quatter.
    you turned , please waiting......
    
    random winner == 0
    a candy comes rolling out the slot....
    === I own 42 candies, and stay in NO_QUARTER state. ===
    
【3】状态模式介绍
1)基本常识:策略模式和状态模式是双胞胎,在出生时才分开;
2)策略模式和状态模式:策略模式是围绕可以互换的算法来创建成功业务的;状态模式通过改变对象的内部状态来帮助对象控制自己的行为;
3)状态模式定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类;
4)因为这个模式将状态封装为独立的类,并将动作委托到代表当前状态的类,我们知道行为会随着内容部状态而改变;

【4】状态模式和策略模式的区别
4.1)状态模式:我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个。随着时间的流失,当前状态在状态对象集合中游走改变,以反映出 context内部的状态,因此,context的行为也会跟着改变;
4.2)策略模式:客户通常主动指定Context 所要组合的策略对象是哪一个。现在,固然策略模式让我们具有弹性,能够在运行时改变策略。但对于某个context对象来说,通常都只有一个 最适当的策略对象。
4.3)Conclusion:
  • C1)一般而言,我们把策略模式想成是除了继承外的一种弹性替代方案。如果你使用继承定义了一个类的行为,你将被这个行为所困住,甚至要修改他都很难。有了策略模式,你可以通过组合不同对象来改变行为;
  • C2)我们把状态模式想成是不用在 context 中放置许多条件判断的替代方案。通过将行为包装进状态对象中,你可以通过 context 内简单地修改状态对象来改变context 的行为;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
workflow模式是一种将复杂业务流程分解为一系列相互关联的任务或步骤的方法。它通常用于管理和协调复杂的业务流程,可以帮助组织优化和提高业务流程的效率和可靠性。workflow模式的核心是定义和执行一系列任务以及规定任务之间的关系和依赖。 分布式事务是指涉及多个独立计算机节点的事务处理过程。在分布式系统中,将一个业务操作分为多个子操作,这些子操作可以在不同的计算机节点上并行执行。分布式事务的目标是确保在系统的各个节点上执行的所有子操作都能够同时成功或同时失败。 在分布式系统中实现分布式事务需要解决一些特殊的挑战,例如数据一致性和并发控制。常见的分布式事务处理模式包括两阶段提交和补偿事务模式。 两阶段提交(2PC)是一种分布式事务处理模式,它通过一个协调者节点来管理分布式事务的执行。2PC将事务执行过程分为准备阶段和提交阶段。在准备阶段,协调者节点将询问所有参与者节点是否准备好进行提交操作。如果所有参与者节点都准备好,协调者节点发送提交命令,否则发送回滚命令。 补偿事务模式(Compensating Transaction)是一种在分布式系统中处理事务的并发和错误情况的模式。当一个分布式事务发生错误或被取消时,补偿事务模式通过执行逆操作来回滚已经执行的操作,使系统恢复到原始状态。补偿事务模式可以通过设计逆操作来保持系统的一致性。 总而言之,workflow模式可以用来管理复杂的业务流程,而分布式事务可以保证在分布式系统中执行的各个子操作的一致性。在实现分布式事务时,常用的模式包括两阶段提交和补偿事务模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值