• 设计模式21——行为型模式之状态模式


    定义状态模式(State Pattern),允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

    类型对象行为型模式

    概述:

             一个对象有一个状态,那么每一个状态又对应一些相应的行为。如果这个对象有很多状态,那么就要对应非常多的行为。那么对这些状态的判断以及根据状态完成相应的行为,会非常复杂。并且如果想添加一种新的状态时,需要修改很多的现有代码。这也是有违开闭原则的。状态模式正是在这样一种情况下提出来的。

            状态模式将每种状态对应的行为抽象出来成为单独的新的对象,这样将状态转换显式化了。状态的变换不再依赖于Context内部的行为了。另外,将状态及行为提出来能够大为降低Context对象的复杂度。另外如果一个State对应多个Context时,State还可以被多个Context对象共享。

            状态,我们立马会提出,今天状态不好,做什么都没劲;又或者是今天状态很好,做事得劲,饭也吃得多。那么我们就以一个人不同时刻的状态为例来讲解状态模式。

    类图:

    参与者:

    1. Human,也即Context通过抽象接口来调用状态对象的具体实现。
    1. State,封装了与Human相关行为的接口。
    1. HappySad,具体实现了与相应状态下的行为。

    示例代码:

    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4.   
    5. namespace Pattern21  
    6. {  
    7.     //抽象状态   
    8.     public abstract class State  
    9.     {  
    10.         public abstract void Eat();  
    11.         public abstract void Walk();  
    12.     }  
    13.   
    14.     // 高兴时的状态   
    15.     public class Happy : State  
    16.     {  
    17.         public override void Eat()  
    18.         {  
    19.             human.Eat();  
    20.             Console.WriteLine("很多!");  
    21.         }  
    22.   
    23.         public override void Walk()  
    24.         {  
    25.             human.Walk();  
    26.             Console.WriteLine("手舞足蹈的!");  
    27.         }  
    28.   
    29.         public void Attach(Human _human)  
    30.         {  
    31.             human = _human;  
    32.         }  
    33.   
    34.         private Human human;  
    35.     }  
    36.   
    37.     // 伤心时的状态   
    38.     public class Sad : State  
    39.     {  
    40.         public override void Eat()  
    41.         {  
    42.             human.Eat();  
    43.             Console.WriteLine("很少!");  
    44.         }  
    45.   
    46.         public override void Walk()  
    47.         {  
    48.             human.Walk();  
    49.             Console.WriteLine("无精打采的!");  
    50.         }  
    51.   
    52.         public void Attach(Human _human)  
    53.         {  
    54.             human = _human;  
    55.         }  
    56.   
    57.         private Human human;  
    58.     }  
    59.      
    60.   
    61.     // 一个人   
    62.     public class Human  
    63.     {  
    64.         private State current;  
    65.   
    66.         public void SetState(State s)  
    67.         {  
    68.             current = s;  
    69.         }  
    70.   
    71.         public void Eat()  
    72.         {  
    73.             Console.Write("吃了");  
    74.         }  
    75.   
    76.         public void Walk()  
    77.         {  
    78.             Console.Write("走起路来");  
    79.         }  
    80.   
    81.         public void Show()  
    82.         {  
    83.             current.Eat();  
    84.             current.Walk();  
    85.         }  
    86.     }  
    87.     class Program  
    88.     {  
    89.         static void Main(string[] args)  
    90.         {  
    91.             // 定义一个有很多状态的对象   
    92.             Human human = new Human();  
    93.   
    94.             // 定义一个高兴的状态   
    95.             Happy hState = new Happy();  
    96.             hState.Attach(human);  
    97.             human.SetState(hState);  
    98.             human.Show();  
    99.   
    100.             // 定义一个伤心的状态   
    101.             Sad sad = new Sad();  
    102.             sad.Attach(human);  
    103.             human.SetState(sad);  
    104.             human.Show();  
    105.   
    106.             // 还可以添加生病的状态,只需要添加新的类而不需要修改Human类   
    107.             // ......   
    108.   
    109.             Console.Read();  
    110.         }  
    111.     }  
    112. }  

    适用性:

    1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
    2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

    优缺点:

    1. 优点,将状态判断的逻辑移到类外面,方便通过添加新类来添加新的状态。
    2. 缺点,如果状态非常多,会导致有非常多的状态类,加大开销。

    参考资料:

    1. 《设计模式——可复用面向对象软件基础》
    2. 《大话设计模式》
  • 相关阅读:
    PL/SQL异常处理
    spool命令
    Oracle循环语句
    替换变量&和&&
    OCP-052 & 053部分答案解析
    Oracle IF & CASE语句
    PL/SQL概念
    AIX下如何根据端口号查找相应的进程
    (转)Tomcat启动报Error listenerStart错误
    Suse碎碎念
  • 原文地址:https://www.cnblogs.com/feihe0755/p/3597664.html
Copyright © 2020-2023  润新知