【转】设计模式 ( 十七) 状态模式State(对象行为型)

设计模式 ( 十七) 状态模式State(对象行为型)

1.概述

 

在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理。最直接的解决方案是将这些所有可能发生的情况全都考虑到。然后使用if... ellse语句来做状态判断来进行不同情况的处理。但是对复杂状态的判断就显得“力不从心了”。随着增加新的状态或者修改一个状体(if else(或switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变得很弱。维护也会很麻烦。那么我们就需要考虑实现只修改自身状态的模式。

例子1:按钮来控制一个电梯的状态,一个电梯开门,关门,停止,运行。每一种状态改变,都有可能要根据其他状态来更新处理。例如,开门状态,你不能在运行的时候开门,而是在电梯停下后才能开门。

例子2:我们给一部手机打电话,就可能出现这几种情况:用户开机,用户关机,用户欠费停机,用户销户等。 所以当我们拨打这个号码的时候:系统就要判断,该用户是否在开机且不忙状态,又或者是关机,欠费等状态。但不管是那种状态我们都应给出对应的处理操作。

 

2.问题

 

对象如何在每一种状态下表现出不同的行为?

 

3.解决方案

 

状态模式:允许一个对象在其内部状态改变时改变它的行为,使得对象看起来似乎修改了它的类。

在很多情况下, 一个对象的行为取决于一个或多个动态变化的属性 ,这样的属性叫做 状态 ,这样的对象叫做 有状态的 ( stateful ) 对象 ,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。

 

 

4.适用性

 

 

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

 

 

5.结构

 

 

6.模式的组成

 

环境类(Context):  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
抽象状态类(State):  定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态类(ConcreteState):  每一子类实现一个与Context的一个状态相关的行为。

 

7.效果

 

State模式有下面一些效果:
状态模式的优点:
1 ) 它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来: State模式将所有与一个特定的状态相关的行为都放入一个对象中。因为所有与状态相关的代码都存在于某一个State子类中, 所以通过定义新的子类可以很容易的增加新的状态和转换。另一个方法是使用数据值定义内部状态并且让 Context操作来显式地检查这些数据。但这样将会使整个Context的实现中遍布看起来很相似的条件if else语句或switch case语句。增加一个新的状态可能需要改变若干个操作, 这就使得维护变得复杂了。State模式避免了这个问题, 但可能会引入另一个问题, 因为该模式将不同状态的行为分布在多个State子类中。这就增加了子类的数目,相对于单个类的实现来说不够紧凑。但是如果有许多状态时这样的分布实际上更好一些, 否则需要使用巨大的条件语句。正如很长的过程一样,巨大的条件语句是不受欢迎的。它们形成一大整块并且使得代码不够清晰,这又使得它们难以修改和扩展。 State模式提供了一个更好的方法来组织与特定状态相关的代码。决定状态转移的逻辑不在单块的 i f或s w i t c h语句中, 而是分布在State子类之间。将每一个状态转换和动作封装到一个类中,就把着眼点从执行状态提高到整个对象的状态。这将使代码结构化并使其意图更加清晰。

2) 它使得状态转换显式化: 当一个对象仅以内部数据值来定义当前状态时 , 其状态仅表现为对一些变量的赋值,这不够明确。为不同的状态引入独立的对象使得转换变得更加明确。而且, State对象可保证Context不会发生内部状态不一致的情况,因为从 Context的角度看,状态转换是原子的—只需重新绑定一个变量(即Context的State对象变量),而无需为多个变量赋值

3) State对象可被共享 如果State对象没有实例变量—即它们表示的状态完全以它们的类型来编码—那么各Context对象可以共享一个State对象。当状态以这种方式被共享时, 它们必然是没有内部状态, 只有行为的轻量级对象。

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

 

8.实现

我们用电梯的例子来说明:

简单地实现代码:

 

 
  1. <?php

  2. abstract class ILift {

  3. //电梯的四个状态

  4. const OPENED_STATE = 1; //门敞状态

  5. const CLOSED_STATE = 2; //门闭状态

  6. const RUNNING_STATE = 3; //运行状态

  7. const STOPPED_STATE = 4; //停止状态;

  8.  
  9.  
  10. //设置电梯的状态

  11. public abstract function setState($state);

  12.  
  13. //首先电梯门开启动作

  14. public abstract function open();

  15.  
  16. //电梯门有开启,那当然也就有关闭了

  17. public abstract function close();

  18.  
  19. //电梯要能上能下,跑起来

  20. public abstract function run();

  21.  
  22. //电梯还要能停下来,停不下来那就扯淡了

  23. public abstract function stop();

  24. }

  25.  
  26. /**

  27. * 电梯的实现类

  28. */

  29. class Lift extends ILift {

  30. private $state;

  31.  
  32. public function setState($state) {

  33. $this->state = $state;

  34. }

  35. //电梯门关闭

  36. public function close() {

  37. //电梯在什么状态下才能关闭

  38. switch($this->state){

  39. case ILift::OPENED_STATE: //如果是则可以关门,同时修改电梯状态

  40. $this->setState(ILift::CLOSED_STATE);

  41. break;

  42. case ILift::CLOSED_STATE: //如果电梯就是关门状态,则什么都不做

  43. //do nothing;

  44. return ;

  45. break;

  46. case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做

  47. //do nothing;

  48. return ;

  49. break;

  50. case ILift::STOPPED_STATE: //如果是停止状态,本也是关闭的,什么也不做

  51. //do nothing;

  52. return ;

  53. break;

  54. }

  55. echo 'Lift colse <br>';

  56. }

  57.  
  58. //电梯门开启

  59. public function open() {

  60. //电梯在什么状态才能开启

  61. switch($this->state){

  62. case ILift::OPENED_STATE: //如果已经在门敞状态,则什么都不做

  63. //do nothing;

  64. return ;

  65. break;

  66. case ILift::CLOSED_STATE: //如是电梯时关闭状态,则可以开启

  67. $this->setState(ILift::OPENED_STATE);

  68. break;

  69. case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做

  70. //do nothing;

  71. return ;

  72. break;

  73. case ILift::STOPPED_STATE: //停止状态,淡然要开门了

  74. $this->setState(ILift::OPENED_STATE);

  75. break;

  76. }

  77. echo 'Lift open <br>';

  78. }

  79. ///电梯开始跑起来

  80. public function run() {

  81. switch($this->state){

  82. case ILift::OPENED_STATE: //如果已经在门敞状态,则不你能运行,什么都不做

  83. //do nothing;

  84. return ;

  85. break;

  86. case ILift::CLOSED_STATE: //如是电梯时关闭状态,则可以运行

  87. $this->setState(ILift::RUNNING_STATE);

  88. break;

  89. case ILift::RUNNING_STATE: //正在运行状态,则什么都不做

  90. //do nothing;

  91. return ;

  92. break;

  93. case ILift::STOPPED_STATE: //停止状态,可以运行

  94. $this->setState(ILift::RUNNING_STATE);

  95. }

  96. echo 'Lift run <br>';

  97. }

  98.  
  99. //电梯停止

  100. public function stop() {

  101. switch($this->state){

  102. case ILift::OPENED_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做

  103. //do nothing;

  104. return ;

  105. break;

  106. case ILift::CLOSED_STATE: //如是电梯时关闭状态,则当然可以停止了

  107. $this->setState(ILift::CLOSED_STATE);

  108. break;

  109. case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了

  110. $this->setState(ILift::CLOSED_STATE);

  111. break;

  112. case ILift::STOPPED_STATE: //停止状态,什么都不做

  113. //do nothing;

  114. return ;

  115. break;

  116. }

  117. echo 'Lift stop <br>';

  118. }

  119.  
  120. }

  121. $lift = new Lift();

  122.  
  123. //电梯的初始条件应该是停止状态

  124. $lift->setState(ILift::STOPPED_STATE);

  125. //首先是电梯门开启,人进去

  126. $lift->open();

  127.  
  128. //然后电梯门关闭

  129. $lift->close();

  130.  
  131. //再然后,电梯跑起来,向上或者向下

  132. $lift->run();

  133. //最后到达目的地,电梯挺下来

  134. $lift->stop();

 

显然我们已经完成了我们的基本业务操作,但是,我们在程序中使用了大量的switch…case这样的判断(if…else也是一样),首先是程序的可阅读性很差,其次扩展非常不方便。一旦我们有新的状态加入的话,例如新加通电和断点状态。我们势必要在每个业务方法里边增加相应的case语句。也就是四个函数open,close,run,stop都需要修改相应case语句。

状态模式:把不同状态的操作分散到不同的状态对象里去完成。看看状态类的uml类图:

代码实现:

 

 
  1. <?php

  2. /**

  3. *

  4. * 定义一个电梯的接口

  5. */

  6. abstract class LiftState{

  7.  
  8. //定义一个环境角色,也就是封装状态的变换引起的功能变化

  9. protected $_context;

  10.  
  11. public function setContext(Context $context){

  12. $this->_context = $context;

  13. }

  14.  
  15. //首先电梯门开启动作

  16. public abstract function open();

  17.  
  18. //电梯门有开启,那当然也就有关闭了

  19. public abstract function close();

  20.  
  21. //电梯要能上能下,跑起来

  22. public abstract function run();

  23.  
  24. //电梯还要能停下来,停不下来那就扯淡了

  25. public abstract function stop();

  26.  
  27. }

  28.  
  29.  
  30. /**

  31. * 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。

  32. */

  33. class Context {

  34. //定义出所有的电梯状态

  35. static $openningState = null;

  36. static $closeingState = null;

  37. static $runningState = null;

  38. static $stoppingState = null;

  39.  
  40. public function __construct() {

  41. self::$openningState = new OpenningState();

  42. self::$closeingState = new ClosingState();

  43. self::$runningState = new RunningState();

  44. self::$stoppingState = new StoppingState();

  45.  
  46. }

  47.  
  48. //定一个当前电梯状态

  49. private $_liftState;

  50.  
  51. public function getLiftState() {

  52. return $this->_liftState;

  53. }

  54.  
  55. public function setLiftState($liftState) {

  56. $this->_liftState = $liftState;

  57. //把当前的环境通知到各个实现类中

  58. $this->_liftState->setContext($this);

  59. }

  60.  
  61.  
  62. public function open(){

  63. $this->_liftState->open();

  64. }

  65.  
  66. public function close(){

  67. $this->_liftState->close();

  68. }

  69.  
  70. public function run(){

  71. $this->_liftState->run();

  72. }

  73.  
  74. public function stop(){

  75. $this->_liftState->stop();

  76. }

  77. }

  78.  
  79. /**

  80. * 在电梯门开启的状态下能做什么事情

  81. */

  82. class OpenningState extends LiftState {

  83.  
  84. /**

  85. * 开启当然可以关闭了,我就想测试一下电梯门开关功能

  86. *

  87. */

  88. public function close() {

  89. //状态修改

  90. $this->_context->setLiftState(Context::$closeingState);

  91. //动作委托为CloseState来执行

  92. $this->_context->getLiftState()->close();

  93. }

  94.  
  95. //打开电梯门

  96. public function open() {

  97. echo 'lift open...', '<br/>';

  98. }

  99. //门开着电梯就想跑,这电梯,吓死你!

  100. public function run() {

  101. //do nothing;

  102. }

  103.  
  104. //开门还不停止?

  105. public function stop() {

  106. //do nothing;

  107. }

  108.  
  109. }

  110.  
  111. /**

  112. * 电梯门关闭以后,电梯可以做哪些事情

  113. */

  114. class ClosingState extends LiftState {

  115.  
  116. //电梯门关闭,这是关闭状态要实现的动作

  117. public function close() {

  118. echo 'lift close...', '<br/>';

  119.  
  120. }

  121. //电梯门关了再打开,逗你玩呢,那这个允许呀

  122. public function open() {

  123. $this->_context->setLiftState(Context::$openningState); //置为门敞状态

  124. $this->_context->getLiftState()->open();

  125. }

  126.  
  127. //电梯门关了就跑,这是再正常不过了

  128. public function run() {

  129. $this->_context->setLiftState(Context::$runningState); //设置为运行状态;

  130. $this->_context->getLiftState()->run();

  131. }

  132.  
  133. //电梯门关着,我就不按楼层

  134.  
  135. public function stop() {

  136. $this->_context->setLiftState(Context::$stoppingState); //设置为停止状态;

  137. $this->_context->getLiftState()->stop();

  138. }

  139.  
  140. }

  141.  
  142. /**

  143. * 电梯在运行状态下能做哪些动作

  144. */

  145. class RunningState extends LiftState {

  146.  
  147. //电梯门关闭?这是肯定了

  148. public function close() {

  149. //do nothing

  150. }

  151.  
  152. //运行的时候开电梯门?你疯了!电梯不会给你开的

  153. public function open() {

  154. //do nothing

  155. }

  156.  
  157. //这是在运行状态下要实现的方法

  158. public function run() {

  159. echo 'lift run...', '<br/>';

  160. }

  161.  
  162. //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了

  163. public function stop() {

  164. $this->_context->setLiftState(Context::$stoppingState); //环境设置为停止状态;

  165. $this->_context->getLiftState()->stop();

  166. }

  167.  
  168. }

  169.  
  170.  
  171.  
  172. /**

  173. * 在停止状态下能做什么事情

  174. */

  175. class StoppingState extends LiftState {

  176.  
  177. //停止状态关门?电梯门本来就是关着的!

  178. public function close() {

  179. //do nothing;

  180. }

  181.  
  182. //停止状态,开门,那是要的!

  183. public function open() {

  184. $this->_context->setLiftState(Context::$openningState);

  185. $this->_context->getLiftState()->open();

  186. }

  187. //停止状态再跑起来,正常的很

  188. public function run() {

  189. $this->_context->setLiftState(Context::$runningState);

  190. $this->_context->getLiftState()->run();

  191. }

  192. //停止状态是怎么发生的呢?当然是停止方法执行了

  193. public function stop() {

  194. echo 'lift stop...', '<br/>';

  195. }

  196.  
  197. }

  198.  
  199. /**

  200. * 模拟电梯的动作

  201. */

  202. class Client {

  203.  
  204. public static function main() {

  205. $context = new Context();

  206. $context->setLiftState(new ClosingState());

  207.  
  208. $context->open();

  209. $context->close();

  210. $context->run();

  211. $context->stop();

  212. }

  213. }

  214. Client::main();

 

9.与其他相关模式

 

1)职责链模式,
职责链模式和状态模式都可以解决If分支语句过多,
从定义来看,状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定),
而职责链模式是多个对象之间的改变(多个对象之间的话,就会出现某个对象不存在的现在,就像我们举例的公司请假流程,经理可能不在公司情况),这也说明他们两个模式处理的情况不同。
这两个设计模式最大的区别就是状态模式是让各个状态对象自己知道其下一个处理的对象是谁。
而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。
用我们通俗的编程语言来说,就是
状态模式:
  相当于If else if else;
  设计路线:各个State类的内部实现(相当于If,else If内的条件)
  执行时通过State调用Context方法来执行。
职责链模式:
  相当于Swich case
  设计路线:客户设定,每个子类(case)的参数是下一个子类(case)。
  使用时,向链的第一个子类的执行方法传递参数就可以。
就像对设计模式的总结,有的人采用的是状态模式,从头到尾,提前一定定义好下一个处理的对象是谁,而我采用的是职责链模式,随时都有可能调整链的顺序。

2) 策略模式:(http://www.cnblogs.com/Mainz/archive/2007/12/15/996081.html)(状态模式是策略模式的孪生兄弟)
        状态模式和策略模式的实现方法非常类似,都是利用多态把一些操作分配到一组相关的简单的类中,因此很多人认为这两种模式实际上是相同的。
然而在现实世界中,策略(如促销一种商品的策略)和状态(如同一个按钮来控制一个电梯的状态,又如手机界面中一个按钮来控制手机)是两种完全不同的思想。当我们对状态和策略进行建模时,这种差异会导致完全不同的问题。例如,对状态进行建模时,状态迁移是一个核心内容;然而,在选择策略时,迁移与此毫无关系。另外,策略模式允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有。
       一个策略是一个计划或方案,通过执行这个计划或方案,我们可以在给定的输入条件下达到一个特定的目标。策略是一组方案,他们可以相互替换;选择一个策略,获得策略的输出。策略模式用于随不同外部环境采取不同行为的场合。我们可以参考微软企业库底层Object Builder的创建对象的strategy实现方式。而状态模式不同,对一个状态特别重要的对象,通过状态机来建模一个对象的状态;状态模式处理的核心问题是状态的迁移,因为在对象存在很多状态情况下,对各个business flow,各个状态之间跳转和迁移过程都是及其复杂的。
       例如一个工作流,审批一个文件,存在新建、提交、已修改、HR部门审批中、老板审批中、HR审批失败、老板审批失败等状态,涉及多个角色交互,涉及很多事件,这种情况下用状态模式(状态机)来建模更加合适;把各个状态和相应的实现步骤封装成一组简单的继承自一个接口或抽象类的类,通过另外的一个Context来操作他们之间的自动状态变换,通过event来自动实现各个状态之间的跳转。在整个生命周期中存在一个状态的迁移曲线,这个迁移曲线对客户是透明的。我们可以参考微软最新的WWF 状态机工作流实现思想。
      在状态模式中,状态的变迁是由对象的内部条件决定,外界只需关心其接口,不必关心其状态对象的创建和转化;
而策略模式里,采取何种策略由外部条件(C)决定。
      他们应用场景(目的)却不一样,State模式重在强调对象内部状态的变化改变对象的行为,Strategy模式重在外部对策略的选择,策略的选择由外部条件决定,
也就是说算法的动态的切换。但由于它们的结构是如此的相似,我们可以认为“状态模式是完全封装且自修改的策略模式”。即状态模式是封装对象内部的状态的,而策略模式是封装算法族的

 

10.总结与分析

 

        状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。

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

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

相关文章

【OSG学习】准备开发调试环境

环境 本人当前使用的环境是VS2013 Ultimate Update5 WIN10。 OSG编译安装 下载编译OSG源码不要克隆github上的源码&#xff0c;而是下载稳定版本的OSG源码进行编译。因为github上的源码处于开发阶段&#xff0c;我们应该优先选择稳定版本&#xff0c;我使用的是OpenSceneGr…

【Qt开发经验】Qt信号槽连接不成功问题原因汇总

以下几种情况会导致信号槽连接不成功&#xff0c;下面分别描述。 1. 拥有信号槽的类&#xff0c;必须继承QObject&#xff0c;声明Q_OBJECT宏。 Qt帮助手册里搜索 “Signals & Slots”&#xff0c;可以看到以下说明&#xff1a; 想要使用信号槽&#xff0c;必须继承QOb…

【转】.Net中的异步编程总结

一直以来很想梳理下我在开发过程中使用异步编程的心得和体会&#xff0c;但是由于我是APM异步编程模式的死忠&#xff0c;当TAP模式和TPL模式出现的时候我并未真正的去接纳这两种模式&#xff0c;所以导致我一直没有花太多心思去整理这两部分异步编程模型。今天在CodeProject上…

学习swing鼠标点击事件心得体会_西门子COMOS软件开发定制学习8-查询列表间的数据交互...

​本篇在西门子COMOS软件开发定制学习6-管理界面定制基础上定制&#xff0c;简单介绍两个查询列表之间的数据交互。实现效果&#xff1a;在左侧列表中选择某一设备&#xff0c;右侧列表自动根据所选设备&#xff0c;显示该设备相关的设计图纸(如PID图纸或电气图纸等)&#xff1…

【转】异步编程:.NET 4.5 基于任务的异步编程模型(TAP)

最近我为大家陆续介绍了“IAsyncResult异步编程模型 (APM)”和“基于事件的异步编程模式(EAP)”两种异步编程模型。在.NET4.0 中Microsoft又为我们引入了新的异步编程模型“基于任务的异步编程模型(TAP)”&#xff0c;并且推荐我们在开发新的多线程应用程序中首选TAP&#xff0…

python实验题_python实验二

安徽工程大学 Python 程序设计 实验报告 班级 物流191 姓名 王凡 学号 3190505102 成绩____________ 日期20200322 指导教师 修宇 【实验名称】 实验二 顺序结构程序设计 【思考题】 &#xff08;注意不要漏答&#xff09; 1、影响题1和题3计算准确性的因素有哪些&#xff1f;如…

解决:VS中进行Qt开发,编译时报错:打不开QWidgets.h等文件的问题

1. 先检查是否通过Qt VS Tools添加了Qt路径和配置了正确的Qt版本&#xff0c;这一步基本上都没问题。 2. 再检查此项目是否配置了正确的Qt版本&#xff0c;右键项目&#xff0c;选择Qt Project Settings&#xff0c;选择你需要的Qt版本即可&#xff0c;不可以为空。 3. 完成上面…

【转】1:C#的三种异步的详细介绍及实现

一、介绍异步的前世今生&#xff1a; 异步编程模型 (APM&#xff0c;Asynchronous Programming Model) 模式&#xff08;也称 IAsyncResult 模式&#xff09;&#xff0c;在此模式中异步操作需要 Begin 和 End 方法&#xff08;比如用于异步写入操作的 BeginWrite 和 EndWrite…

elasticsearch date_Elasticsearch在日志分析领域应用和运维实践

主要讲述了&#xff1a;基于ELK Kafka 的日志分析系统Elasticsearch 优化经验Elasticsearch 运维实践ElasticSearch介绍分布式实时分析搜索引擎&#xff0c;优点包括&#xff1a;查询近实时内存消耗小&#xff0c;搜索速度快可扩展性强高可用数据结构FST(Finite State Transdu…

【转】2:C#TPL探秘

理论&#xff1a; 1、 只要方法是 Task类型的返回值&#xff0c;都可以用 await 来等待调用获取返回值。 2、 如果一个返回 Task类型的方法被标记了 async&#xff0c;那么只要方法内部直接 return T 这个 类型的实例就可以。 3、 一个返回 Task类型的方法没有被标记了 asyn…

Qt添加翻译文件无效或部分无效

原因&#xff1a; QTranslator::load路径错误qApp->installTranslator调用时机应该在所有界面起来之前。命名空间宏导致的问题。如果一个类有命名空间宏&#xff0c;则宏不会转换为命名空间&#xff0c;导致ts文件内的上下文不包含命名空间。上下文对不上导致部分窗口翻译失…

linux shell脚本攻略第3版_「技术干货」师傅说不会写shell脚本的网安不是一个好黑客,实战...

shell脚本&#xff1f;在说什么是shell脚本之前&#xff0c;先说说什么是shell。shell是外壳的意思&#xff0c;就是操作系统的外壳。我们可以通过shell命令来操作和控制操作系统&#xff0c;比如Linux中的Shell命令就包括ls、cd、pwd等等。总结来说&#xff0c;Shell是一个命令…

【转】3:C#异步WaitAll的使用

编写界面如图&#xff1a; private async void button1_Click(object sender, EventArgs e){#region 单个执行的异步&#xff0c;效率慢HttpClient wc new HttpClient();string s1 await wc.GetStringAsync(textBox1.Text);label1.Text s1.Length.ToString();string s2 awa…

Qt实现QTextEdit背景透明

QTextEdit为什么要拿出来单独说&#xff0c;因为它继承自QAbstractScrollArea&#xff0c;一般的设置无效。滚动区域ScrollArea内部有一个widget&#xff0c;需要同时设置ScrollArea和viewport两个窗口才能实现透明。代码如下&#xff1a; m_text_editor->setWindowFlags(Q…

python断点调试_「Python调试器」,快速定位各种疑难杂症!!!

在很多的编辑器其实都带着「调试程序」的功能&#xff0c;比如写 c/c 的 codeblocks&#xff0c;写 Python 的 pycharm&#xff0c;这种图形界面的使用和显示都相当友好&#xff0c;简单方便易学&#xff0c;这个不是我这篇文章要讲的重点。今天主要是想给大家介绍一下 「 Pyth…

【转】C# 温故而知新:Stream篇(—)

目录&#xff1a; 什么是Stream? 什么是字节序列&#xff1f; Stream的构造函数 Stream的重要属性及方法 Stream的示例 Stream异步读写 Stream 和其子类的类图 本章总结 什么是Stream? MSDN 中的解释太简洁了: 提供字节序列的一般视图 &#xff08;我可不想这么理解…

python 画树 递归_数据结构 - python如何递归生成树?

问 题 class Tree: def __init__(self, label): self.root label self.child {} def set_child(self, label, relate): self.child[label] relate def get_root(self): return self.root def get_child(self): return self.child 这么一颗树结构&#xff0c;该如何写 def cr…

java integer valueof_一文读懂什么是Java中的自动拆装箱

本文主要介绍Java中的自动拆箱与自动装箱的有关知识。基本数据类型基本类型&#xff0c;或者叫做内置类型&#xff0c;是Java中不同于类(Class)的特殊类型。它们是我们编程中使用最频繁的类型。Java是一种强类型语言&#xff0c;第一次申明变量必须说明数据类型&#xff0c;第一…

【转】面试:一个单例模式,足以把你秒成渣

去面试&#xff08;对&#xff0c;又去面试&#xff09; 问&#xff1a;单例模式了解吧&#xff0c;来&#xff0c;拿纸和笔写一下单例模式。 我心想&#xff0c;这TM不是瞧不起人吗&#xff1f;我编程十年&#xff0c;能不知道单例模式。 答&#xff1a;&#xff08;.net 平…

【转】SQL 语句执行顺序

From&#xff1a;http://www.jellythink.com/archives/924 Oracle-SQL语句执行原理和完整过程详解&#xff1a;https://wenku.baidu.com/view/398bc427964bcf84b8d57b00.html 详解一条 SQL 语句的执行过程&#xff1a;http://www.cnblogs.com/cdf-opensource-007/p/6502556.h…