七、状态模式

最重要的是与策略模式的区别:

策略模式中,是Client提供了不同的策略给Context;状态模式中,状态转移由Context或State自己管理。

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了他的类。 适用场景: 一个对象的行为取决于他的状态,并且它必须在运行时根据状态改变它的行为; 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。 类图:

行政架构和组织架构 行政组织结构模型图_ide

模式的组成: 环境类Context: 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态; 抽象状态类State: 定义一个接口以封装与Context的一个特定状态相关的行为; 具体状态类ConcreteState: 每一子类实现一个与Context的一个状态相关的行为; 实例:push显示红-〉黄-〉绿,pull显示绿-〉黄-〉红

public interface State
 {
     public void handlePush(Context context);

     public void handlePull(Context context);

     public String getColor();
 }

 public class Context
 {
     private State state = null;

     public State getState()
     {
         return state;
     }

     public void setState(final State state)
     {
         this.state = state;
     }

     public void push()
     {
         state.handlePush(this);
     }

     public void pull()
     {
         state.handlePull(this);
     }

 }

 //RED
 public class ConcreteStateA implements State
 {
     @Override
     public void handlePush(final Context context)
     {
         System.out.print(this.getColor());

         final State state = new ConcreteStateB();
         context.setState(state);
         state.handlePush(context);
     }

     @Override
     public void handlePull(final Context context)
     {
         System.out.print(this.getColor());
     }

     @Override
     public String getColor()
     {
         return "RED";
     }
 }

 //YELLOW
 public class ConcreteStateB implements State
 {
     @Override
     public void handlePush(final Context context)
     {
         System.out.print(this.getColor());

         final State state = new ConcreteStateC();
         context.setState(state);
         state.handlePush(context);

     }

     @Override
     public void handlePull(final Context context)
     {
         System.out.print(this.getColor());

         final State state = new ConcreteStateA();
         context.setState(state);
         state.handlePull(context);
     }

     @Override
     public String getColor()
     {
         return "YELLOW";
     }

 }

 //green
 public class ConcreteStateC implements State
 {
     @Override
     public void handlePush(final Context context)
     {
         System.out.print(this.getColor());
     }

     @Override
     public void handlePull(final Context context)
     {
         System.out.print(this.getColor());

         final State state = new ConcreteStateB();
         context.setState(state);
         state.handlePull(context);

     }

     @Override
     public String getColor()
     {
         return "GREEN";
     }
 } public class Client
 {
     public static void main(final String[] args)
     {
         // YTODO Auto-generated method stub
         final Context context = new Context();
         context.setState(new ConcreteStateA());
         System.out.println("PUSH:");
         context.push();
         System.out.println("\nPULL:");
         context.pull();
     }
 }

结果: PUSH: REDYELLOWGREEN PULL: GREENYELLOWRED

八、桥模式

类图:

行政架构和组织架构 行政组织结构模型图_java_02

  根据业务的功能要求,业务的变化具有两个维度,一个维度是抽象的消息,包括普通消息、加急消息和特急消息,这几个抽象的消息本身就具有一定的关系,加急消息和特急消息会扩展普通消息;另一个维度是在具体的消息发送方式上,包括系统内短消息、邮件和手机短消息,这几个方式是平等的,可被切换的方式。

  

  

现在出现问题的根本原因,就在于消息的抽象和实现是混杂在一起的,这就导致了一个纬度的变化会引起另一个纬度进行相应的变化,从而使得程序扩展起来非常困难。

要想解决这个问题,就必须把这两个纬度分开,也就是将抽象部分和实现部分分开,让它们相互独立,这样就可以实现独立的变化,使扩展变得简单。抽象部分就是各个消息的类型所对应的功能,而实现部分就是各种发送消息的方式。按照桥梁模式的结构,给抽象部分和实现部分分别定义接口,然后分别实现它们就可以了。

  

 源代码

  抽象消息类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public abstract class AbstractMessage {     //持有一个实现部分的对象     MessageImplementor impl;     /**      * 构造方法,传入实现部分的对象      * @param impl  实现部分的对象      */     public AbstractMessage(MessageImplementor impl){         this.impl = impl;     }     /**      * 发送消息,委派给实现部分的方法      * @param message    要发送消息的内容      * @param toUser    消息的接受者      */     public void sendMessage(String message , String toUser){         this.impl.send(message, toUser);     } }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

 

  普通消息类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public class CommonMessage extends AbstractMessage {      public CommonMessage(MessageImplementor impl) {         super(impl);     }     @Override     public void sendMessage(String message, String toUser) {         // 对于普通消息,直接调用父类方法,发送消息即可         super.sendMessage(message, toUser);     } }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  加急消息类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public class UrgencyMessage extends AbstractMessage {      public UrgencyMessage(MessageImplementor impl) {         super(impl);     }     @Override     public void sendMessage(String message, String toUser) {         message = "加急:" + message;         super.sendMessage(message, toUser);     }     /**      * 扩展自己的新功能,监控某消息的处理状态      * @param messageId    被监控的消息编号      * @return    监控到的消息的处理状态      */     public Object watch(String messageId) {         // 根据消息id获取消息的状态,组织成监控的数据对象,然后返回         return null;     } }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  实现发送消息的统一接口

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public interface MessageImplementor {     /**      * 发送消息      * @param message 要发送消息的内容      * @param toUser  消息的接受者      */     public void send(String message , String toUser); }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  系统内短消息的实现类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public class MessageSMS implements MessageImplementor {      @Override     public void send(String message, String toUser) {                  System.out.println("使用系统内短消息的方法,发送消息'"+message+"'给"+toUser);     }  }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  邮件短消息的实现类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public class MessageEmail implements MessageImplementor {      @Override     public void send(String message, String toUser) {         System.out.println("使用邮件短消息的方法,发送消息'"+message+"'给"+toUser);     }  }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  客户端类

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

public class Client {      public static void main(String[] args) {         //创建具体的实现对象         MessageImplementor impl = new MessageSMS();         //创建普通消息对象         AbstractMessage message = new  CommonMessage(impl);         message.sendMessage("加班申请速批","李总");                  //将实现方式切换成邮件,再次发送         impl = new MessageEmail();         //创建加急消息对象         message = new UrgencyMessage(impl);         message.sendMessage("加班申请速批","李总");     }  }

行政架构和组织架构 行政组织结构模型图_行政架构和组织架构_03

  观察上面的例子会发现,采用桥梁模式来实现,抽象部分和实现部分分离开了,可以相互独立的变化,而不会相互影响。因此在抽象部分添加新的消息处理(特急消息),对发送消息的实现部分是没有影响的;反过来增加发送消息的方式(手机短消息),对消息处理部分也是没有影响的。

桥梁模式的优点

  ●  分离抽象和实现部分

  桥梁模式分离了抽象部分和实现部分,从而极大地提供了系统的灵活性。让抽象部分和实现部分独立出来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。

 

  ●  更好的扩展性

  桥梁模式使得抽象部分和实现部分可以分别独立地扩展,而不会相互影响,从而大大提高了系统的可扩展性。

九、适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。

类图:

行政架构和组织架构 行政组织结构模型图_适配器模式_17

Adapter类实现了Target接口,并继承自Adaptee,Adapter类的Request方法重新封装了Adaptee的SpecificRequest方法,实现了适配的目的。

因为Adapter与Adaptee是继承的关系,所以这决定了这个适配器模式是类的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。源(Adaptee)角色:需要适配的类。适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类。

适配器模式有2种,第一种是“面向类的适配器模式”,第二种是“面向对象的适配器模式”。

 

先说“面向类的适配器模式”。顾名思义,这类适配器模式就是主要用于,单一的为某个类而实现适配的这样一种模式,为什么说只为某个类去实现,一会提到,我们先展示这种类适配模式的代码实现。

 

源的代码如下:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public class Person {  
2.       
3. private String name;  
4. private String sex;  
5. private int age;  
6.       
7. public void speakJapanese(){  
8. out.println("I can speak Japanese!");  
9.     }  
10.       
11. public void speakEnglish(){  
12. out.println("I can speak English!");  
13.     }  
14. //以下省略成员变量的get和set方法  
15. }

 

 目标接口的代码如下:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public interface Job {  
2.       
3. public abstract void speakJapanese();  
4. public abstract void speakEnglish();  
5. public abstract void speakFrench();  
6.       
7. }

 适配器的代码如下:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public class Adapter extends Person implements Job{  
2.   
3. public void speakFrench() {  
4.           
5.     }  
6.       
7. }

 

好了,代码看完然后要做一些说明了,之前遗留的一个问题,为什么称其为类适配模式呢?很显然的,Adapter类继承了Person类,而在Java这种单继承的语言中也就意味着,他不可能再去继承其他的类了,这样也就是这个适配器只为Person这一个类服务。所以称其为类适配模式。

 

说完类的适配模式,我们要开始说第2种对象的适配器模式了。对象适配器模式是把“源”作为一个对象聚合到适配器类中。同样的话不多说,贴上代码:

 

源的代码以及目标代码同上,再次不再赘述。

仅贴出适配器代码:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public class Adapter implements Job {  
2.   
3.     Person person;  
4.   
5. public Adapter(Person person) {  
6. this.person = person;  
7.     }  
8.   
9. public void speakEnglish() {  
10.         person.speakEnglish();  
11.     }  
12.   
13. public void speakJapanese() {  
14.         person.speakJapanese();  
15.     }  
16.   
17. //new add  
18. public void speakFrench() {  
19.           
20.     }  
21.   
22. }

 

对象的适配器模式,把“源”作为一个构造参数传入适配器,然后执行接口所要求的方法。这种适配模式可以为多个源进行适配。弥补了类适配模式的不足。

 

现在来对2种适配模式做个分析:

1.类的适配模式用于单一源的适配,由于它的源的单一话,代码实现不用写选择逻辑,很清晰;而对象的适配模式则可用于多源的适配,弥补了类适配模式的不足,使得原本用类适配模式需要写很多适配器的情况不复存在,弱点是,由于源的数目可以较多,所以具体的实现条件选择分支比较多,不太清晰。

2.适配器模式主要用于几种情况:(1)系统需要使用现有的类,但现有的类不完全符合需要。(2)讲彼此没有太大关联的类引进来一起完成某项工作(指对象适配)。

 

最后,再来顺带谈谈默认适配器模式:这种模式的核心归结如下:当你想实现一个接口但又不想实现所有接口方法,只想去实现一部分方法时,就用中默认的适配器模式,他的方法是在接口和具体实现类中添加一个抽象类,而用抽象类去空实现目标接口的所有方法。而具体的实现类只需要覆盖其需要完成的方法即可。代码如下:

接口类:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public interface Job {  
2.       
3. public abstract void speakJapanese();  
4. public abstract void speakEnglish();  
5. public abstract void speakFrench();  
6. public abstract void speakChinese();  
7.       
8. }

抽象类: 

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public abstract class JobDefault implements Job{  
2.   
3. public void speakChinese() {  
4.           
5.     }  
6.   
7. public void speakEnglish() {  
8.           
9.     }  
10.   
11. public void speakFrench() {  
12.           
13.     }  
14.   
15. public void speakJapanese() {  
16.           
17.     }  
18.   
19. }

 

实现类:

[c-sharp]  
      view plain 
      copy 
      
 
      
 
    
1. public class JobImpl extends JobDefault{  
2.       
3. public void speakChinese(){  
4. out.println("I can speak Chinese!");  
5.     }  
6.       
7. }

转载于:https://blog.51cto.com/hyman1994/1663640