假设我们正在开发一个网络下载器应用,该应用有不同的下载状态,包括未下载状态、下载中状态、下载完成状态和下载失败状态。我们可以使用状态模式来管理下载器的状态和行为。
要是不用状态模式,这还真的就乱套了!
看下代码吧。
1 // 抽象状态类 - 下载状态 2 public abstract class DownloadState 3 { 4 public abstract void StartDownload(DownloadContext context); 5 public abstract void PauseDownload(DownloadContext context); 6 public abstract void ResumeDownload(DownloadContext context); 7 public abstract void CancelDownload(DownloadContext context); 8 } 9 10 // 具体状态类 - 未下载状态 11 public class NotDownloadedState : DownloadState 12 { 13 public override void StartDownload(DownloadContext context) 14 { 15 Console.WriteLine("Starting download..."); 16 // 设置状态为下载中状态 17 context.State = new DownloadingState(); 18 } 19 20 public override void PauseDownload(DownloadContext context) 21 { 22 Console.WriteLine("Download has not started yet. Cannot pause."); 23 } 24 25 public override void ResumeDownload(DownloadContext context) 26 { 27 Console.WriteLine("Download has not started yet. Cannot resume."); 28 } 29 30 public override void CancelDownload(DownloadContext context) 31 { 32 Console.WriteLine("Download has not started yet. Cannot cancel."); 33 } 34 } 35 36 // 具体状态类 - 下载中状态 37 public class DownloadingState : DownloadState 38 { 39 public override void StartDownload(DownloadContext context) 40 { 41 Console.WriteLine("Download is already in progress."); 42 } 43 44 public override void PauseDownload(DownloadContext context) 45 { 46 Console.WriteLine("Pausing download..."); 47 // 设置状态为暂停状态 48 context.State = new PausedState(); 49 } 50 51 public override void ResumeDownload(DownloadContext context) 52 { 53 Console.WriteLine("Download is already in progress."); 54 } 55 56 public override void CancelDownload(DownloadContext context) 57 { 58 Console.WriteLine("Cancelling download..."); 59 // 设置状态为下载失败状态 60 context.State = new DownloadFailedState(); 61 } 62 } 63 64 // 具体状态类 - 暂停状态 65 public class PausedState : DownloadState 66 { 67 public override void StartDownload(DownloadContext context) 68 { 69 Console.WriteLine("Resuming download..."); 70 // 设置状态为下载中状态 71 context.State = new DownloadingState(); 72 } 73 74 public override void PauseDownload(DownloadContext context) 75 { 76 Console.WriteLine("Download is already paused."); 77 } 78 79 public override void ResumeDownload(DownloadContext context) 80 { 81 Console.WriteLine("Resuming download..."); 82 // 设置状态为下载中状态 83 context.State = new DownloadingState(); 84 } 85 86 public override void CancelDownload(DownloadContext context) 87 { 88 Console.WriteLine("Cancelling download..."); 89 // 设置状态为下载失败状态 90 context.State = new DownloadFailedState(); 91 } 92 } 93 94 // 具体状态类 - 下载完成状态 95 public class DownloadCompletedState : DownloadState 96 { 97 public override void StartDownload(DownloadContext context) 98 { 99 Console.WriteLine("Download is already completed."); 100 } 101 102 public override void PauseDownload(DownloadContext context) 103 { 104 Console.WriteLine("Download is already completed. Cannot pause."); 105 } 106 107 public override void ResumeDownload(DownloadContext context) 108 { 109 Console.WriteLine("Download is already completed. Cannot resume."); 110 } 111 112 public override void CancelDownload(DownloadContext context) 113 { 114 Console.WriteLine("Download is already completed. Cannot cancel."); 115 } 116 } 117 118 // 具体状态类 - 下载失败状态 119 public class DownloadFailedState : DownloadState 120 { 121 public override void StartDownload(DownloadContext context) 122 { 123 Console.WriteLine("Retrying download..."); 124 // 设置状态为下载中状态 125 context.State = new DownloadingState(); 126 } 127 128 public override void PauseDownload(DownloadContext context) 129 { 130 Console.WriteLine("Download has failed. Cannot pause."); 131 } 132 133 public override void ResumeDownload(DownloadContext context) 134 { 135 Console.WriteLine("Retrying download..."); 136 // 设置状态为下载中状态 137 context.State = new DownloadingState(); 138 } 139 140 public override void CancelDownload(DownloadContext context) 141 { 142 Console.WriteLine("Download has failed. Cannot cancel."); 143 } 144 } 145 146 // 环境类 - 下载器 147 public class DownloadContext 148 { 149 private DownloadState state; 150 151 public DownloadState State 152 { 153 get { return state; } 154 set { state = value; } 155 } 156 157 public DownloadContext() 158 { 159 // 默认状态为未下载状态 160 state = new NotDownloadedState(); 161 } 162 163 public void Start() 164 { 165 state.StartDownload(this); 166 } 167 168 public void Pause() 169 { 170 state.PauseDownload(this); 171 } 172 173 public void Resume() 174 { 175 state.ResumeDownload(this); 176 } 177 178 public void Cancel() 179 { 180 state.CancelDownload(this); 181 } 182 } 183 184 // 客户端代码 185 public class Client 186 { 187 public static void Main(string[] args) 188 { 189 DownloadContext downloader = new DownloadContext(); 190 downloader.Start(); // 输出:"Starting download..." 191 downloader.Pause(); // 输出:"Download has not started yet. Cannot pause." 192 downloader.Resume(); // 输出:"Download has not started yet. Cannot resume." 193 194 // 下载失败,设置状态为下载失败状态 195 downloader.State = new DownloadFailedState(); 196 downloader.Pause(); // 输出:"Download has failed. Cannot pause." 197 downloader.Resume(); // 输出:"Retrying download..." 198 downloader.Cancel(); // 输出:"Download has failed. Cannot cancel." 199 } 200 }
然后来点干巴巴的理论吧:
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,看起来好像是对象类改变了。状态模式的主要目的是将对象的状态转换逻辑从主体对象中分离出来,使得状态的变化不会影响到主体对象的行为,从而提高代码的可维护性和灵活性。
在状态模式中,有三种主要角色:
-
环境(Context):环境是包含状态的对象。它在内部维护一个对抽象状态类的引用,并根据当前状态的不同调用相应的方法。
-
抽象状态(State):抽象状态是一个接口或抽象类,定义了状态的接口,具体状态类必须实现这些接口。
-
具体状态(Concrete State):具体状态是抽象状态的实现,它实现了抽象状态定义的接口,并根据状态的不同提供不同的行为。
状态模式的核心思想是将状态的逻辑封装在具体状态类中,使得环境类不需要关心状态的转换逻辑。当状态发生改变时,环境类只需要将当前状态设置为新状态即可,具体状态类会处理相应的行为。