zoukankan      html  css  js  c++  java
  • iOS开发-状态模式

    状态模式允许对象内部状态改变时改变它的行为,对象看起来好像修改了它的类。状态模式看起来和策略模式比较相像,策略模式是将可以互换的行为封装起来,然后通过使用委托的方式,决定使用哪一个行为,状态也是封装行为,不同的是可以将行为委托到当前状态。一个需要从外部设置,一个是内部通过状态变更达到行为变成的目的。

    基础知识

    状态模式的UML类图:

    State封装基本的状态行为,我们通过Cotext上下文持有状态子类的实例,外部发起请求,我们就可以委托状态进行处理。地铁里面一般都有自动饮料售卖机,我们将所有的饮料都当做商品来看,我们如果需要买饮料需要两步,投币,取货,如果没有商品还可以退钱三种行为,关于自动售卖机的存在无钱状态,有钱状态,售卖中状态,已售罄状态四种状态,稍微思考一下,可以看下面的具体实现。

    设计实战

    状态行为基类: 

    @protocol StateProtocol <NSObject>
    
    @optional
    -(void)putMoney;
    @optional
    -(void)ejectMoney;
    @optional
    -(void)pressButton;
    @optional
    -(void)distribute;
    
    @end
    
    @interface State : NSObject<StateProtocol>
    
    @end
    

    售卖机处于无钱状态(NoMoneyState):

    @protocol NoMoneyDelegate <NSObject>
    
    -(void)setCurrentState:(State *)currentState;
    
    -(State *)geHasMoneyState;
    
    @end
    
    //没钱状态
    @interface NoMoneyState : State
    
    @property (weak,nonatomic) id<NoMoneyDelegate>  delegate;
    
    @end
    
    @implementation NoMoneyState
    
    -(void)putMoney{
        NSLog(@"NoMoneyState-putMoney:投放钱币");
        [self.delegate setCurrentState:[self.delegate geHasMoneyState]];
    }
    
    -(void)ejectMoney{
         NSLog(@"NoMoneyState-ejectMoney:没有投入钱币,无法退钱");
    }
    
    -(void)pressButton{
        NSLog(@"NoMoneyState-pressButton:请先投币");
    }
    
    -(void)distribute{
         NSLog(@"NoMoneyState-pressButton:请投币");
    }
    
    @end
    

    售卖机处于有钱状态(HasMoneyState):

    @protocol  HasMoneyDelegate <NSObject>
    
    -(void)setCurrentState:(State *)currentState;
    
    -(State *)getNoMoneyState;
    
    -(State *)getSoldState;
    
    @end
    //有钱状态
    @interface HasMoneyState : State
    
    @property (weak,nonatomic) id<HasMoneyDelegate> delegate;
    
    @end
    
    @implementation HasMoneyState
    
    -(void)putMoney{
        NSLog(@"HasMoneyState-putMoney:已经投入了钱,暂不支持投入");
    }
    
    -(void)ejectMoney{
        NSLog(@"HasMoneyState-ejectMoney:退钱,重新设置售卖机为无前状态");
        [self.delegate setCurrentState:[self.delegate getNoMoneyState]];
    }
    
    -(void)pressButton{
       NSLog(@"HasMoneyState-pressButton:按钮按下,取货");
       [self.delegate setCurrentState:[self.delegate getSoldState]];
    }
    
    -(void)distribute{
      NSLog(@"HasMoneyState-distribute:无法进行取出商品");
    }
    
    @end
    

    售卖机处于售卖状态:

    @protocol  SoldDelegate <NSObject>
    
    -(void)setCurrentState:(State *)currentState;
    
    -(void)realseProduct;
    
    -(NSInteger)getCurrentCount;
    
    -(State *)getNoMoneyState;
    
    -(State *)getSoldOutState;
    
    @end
    //售出状态
    @interface SoldState : State
    
    @property (weak,nonatomic) id<SoldDelegate> delegate;
    
    @end
    @implementation SoldState
    
    -(void)putMoney{
        NSLog(@"SoldState-putMoney:请稍后,正在进行商品出售");
    }
    
    -(void)ejectMoney{
         NSLog(@"SoldState-putMoney:请稍后,正在进行商品出售,无法退钱");
    }
    
    -(void)pressButton{
        NSLog(@"SoldState-putMoney:请在取出物品之后重新投币");
    }
    
    -(void)distribute{
        [self.delegate realseProduct];
        if ([self.delegate getCurrentCount]) {
            [self.delegate setCurrentState:[self.delegate getNoMoneyState]];
        }else{
            [self.delegate setCurrentState:[self.delegate getSoldOutState]];
        }
    }
    
    @end
    

    售罄状态(SoldOutState):

    @protocol  SoldOutDelegate <NSObject>
    
    -(void)setCurrentState:(State *)currentState;
    
    @end
    //售罄状态
    @interface SoldOutState : State
    
    @property (weak,nonatomic) id<SoldOutDelegate>  delegate;
    
    @end
    
    @implementation SoldOutState
    
    -(void)putMoney{
        NSLog(@"SoldOutState-PutMoney:已售罄");
    }
    
    -(void)ejectMoney{
        NSLog(@"SoldOutState-ejectMoney:无法退钱");
    }
    
    -(void)pressButton{
        NSLog(@"SoldOutState-pressButton:无法售出");
    }
    
    -(void)distribute{
        NSLog(@"SoldOutState-distribute:无法分发");
    }
    
    @end
    

    售卖机(SaleMachine):

    @interface SaleMachine : NSObject<NoMoneyDelegate,HasMoneyDelegate,SoldOutDelegate,SoldDelegate>
    
    @property  (strong,nonatomic) NoMoneyState  *noMoneyState;
    @property  (strong,nonatomic) HasMoneyState *hasMoneyState;
    @property  (strong,nonatomic) SoldOutState  *soldOutState;
    @property  (strong,nonatomic) SoldState     *soldState;
    
    -(instancetype)initWithCount:(NSInteger)count;
    
    -(void)setCurrentState:(State *)currentState;
    
    -(void)putMoney;
    -(void)ejectMoney;
    -(void)pressButton;
    
    @end
    
    @interface SaleMachine()
    
    @property (strong,nonatomic)  State *state;
    @property (assign,nonatomic)  NSInteger  productCount;
    
    @end
    
    @implementation SaleMachine
    
    -(instancetype)initWithCount:(NSInteger)count{
        self=[super init];
        if (self) {
            self.noMoneyState=[[NoMoneyState alloc]init];
            self.noMoneyState.delegate=self;
            self.hasMoneyState=[[HasMoneyState alloc]init];
            self.hasMoneyState.delegate=self;
            self.soldState=[[SoldState alloc]init];
            self.soldState.delegate=self;
            self.soldOutState=[[SoldOutState alloc]init];
            self.soldOutState.delegate=self;
            self.productCount=count;
            if (count) {
                self.state=self.noMoneyState;
            }
        }
        return self;
    }
    
    -(void)putMoney{
        [self.state putMoney];
    }
    
    -(void)ejectMoney{
        [self.state ejectMoney];
    }
    
    -(void)pressButton{
        [self.state pressButton];
        [self.state distribute];
    }
    
    -(void)setCurrentState:(State *)currentState{
        self.state=currentState;
    }
    #pragma mark - NoMoenyDelegate
    -(State *)geHasMoneyState{
        return self.hasMoneyState;
    }
    
    #pragma mark - HasMoneyDelegate
    -(State *)getNoMoneyState{
        return self.noMoneyState;
    }
    
    -(State *)getSoldState{
        return self.soldState;
    }
    #pragma mark - SoldDelegate
    -(void)realseProduct{
        NSLog(@"SoldDelegate-realseProduct:商品售出");
        if (self.productCount) {
            self.productCount-=1;
        }
    }
    
    -(State *)getSoldOutState{
        return self.soldOutState;
    }
    
    -(NSInteger)getCurrentCount{
        return self.productCount;
    }
    
    @end
    

    测试:

        SaleMachine *machine=[[SaleMachine alloc]initWithCount:1];
        [machine putMoney];
        [machine ejectMoney];
        
        [machine putMoney];
        [machine pressButton];
        
        SaleMachine *next=[[SaleMachine alloc]initWithCount:1];
        [next putMoney];
        [next ejectMoney];
    

    测试效果:

      

    状态模式的优缺点:

    优点:状态模式允许一个对象基于内部状态有不同的行为,将行为委托给状态对象执行,状态转化可以由Context也可以由状态行为控制,比较灵活;

    缺点: 状态模式的使用必然会增加系统类和对象的个数。状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

  • 相关阅读:
    冷门Javascript API——element.insertAdjacentHTML
    一些CKEditor定制问题
    HTML中的base标签
    深入Require.js
    狂神说SpringMVC笔记
    GeoServer之Dispatcher类(Controller控制器)
    java之ThreadLocal<>线程
    java获取当前路径&文件读写
    GeoServer服务扩展
    Spring之getBeanNamesForType
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/5135479.html
Copyright © 2011-2022 走看看