访问者(vistor)模式

       访问者(vistor)模式的定义是,作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作。

        假设有男人和女人两种元素,要分别打印出他们在不同状态时的不同表现。 用OO的思想把表现(行为)提取出来作为一个抽象方法,代码如下:

public interface Person {  
	public void action(String state);  
}  

public class Man implements Person{  
 
    public void action(String state) {  
        if(state == "success"){   
           System.out.println("当男人成功时,背后多半有一个伟大的女人");   
        }  
       else if(state == "love"){   
            System.out.println("当男人恋爱时,凡事不懂也装懂");   
        }  
    }      
}

public class Woman implements Person{  
  
    public void action(String state) {  
        if(state == "success"){   
            System.out.println("当女人成功时,背后大多有一个不成功的男人");   
        }  
        else if(state == "love"){   
            System.out.println("当女人恋爱时,遇事懂也装不懂");   
        }  
    }   
  
} 

       当需求发生变化时,要增加一种失败状态时,增加男人女人的不同表现,这时就要修改Man类与Woman类的if else,违反了ocp原则(对增加开放-对修改封闭)。而且随着需求的增加,Man类与Woman类的if,else越来越臃肿,需要取消时,又要去修改if,else,既不方便,又容易出错。 这时候访问者模式可以派上用场了。

       把状态抽象出来成为一个接口(访问者),不同的状态就作为状态的不同实现类(不同的访问者)。

public interface Visitor {  
      public void visit(Man man);  
      public void visit(Woman woman);  
}  

//成功时Man与Woman的不同表现   
public class Success implements Visitor{  
  
    public void visit(Man man) {  
        System.out.println("当男人成功时,背后多半有一个伟大的女人");   
    }   
  
    public void visit(Woman woman) {  
        System.out.println("当女人成功时,背后大多有一个不成功的男人");   
    }   
}   
  
  
public class Love implements Visitor{   
  
    public void visit(Man man) {  
        System.out.println("当男人恋爱时,凡事不懂也装懂");   
    }   
  
    public void visit(Woman woman) {  
        System.out.println("当女人恋爱时,遇事懂也装不懂");   
    }   
}  

         被访问的Person类也要改一下。

public interface Person {  
      void accept(Visitor visitor);  
}   
  
  
public class Man implements Person{   
  
    public void accept(Visitor visitor) {  
        visitor.visit(this);   
    }   
}   
  
  
public class Woman implements Person{  
  
    public void accept(Visitor visitor) {  
          visitor.visit(this);   
    }   
}

          客户端测试代码:

public static void main(String[] args) {  
    List<Person> elements = new ArrayList<Person>();
    elements.add(new Man());
    elements.add(new Woman());

    Visitor success = new Success();
    Visitor love = new Love(); 
    
    for(Person p:elements){  
        p.accept(success); 
        p.accept(love); 
    } 
         
}

        经重构后系统类图如下:

这时如果要增加一种状态的不同操作,只需要增加一个具体访问者,无需要修改具体元素类Man与Woman。

public class Fail implements Visitor{  
  
    public void visit(Man man) {  
        System.out.println("当男人失败时,闷头喝酒,谁也不用劝");   
    }   
  
    public void visit(Woman woman) {  
        System.out.println("当女人失败时,眼泪汪汪,谁也劝不了");   
    }   
} 

        使用了访问者模式以后,对于原来的类层次增加新的操作,仅仅需要实现一个具体访问者角色就可以了,而不必修改整个类层次,使得类层次结构的代码臃肿难以维护。而且这样符合“开闭原则”的要求。而且每个具体的访问者角色都对应于一个相关操作,因此如果一个操作的需求有变,那么仅仅修改一个具体访问者角色,而不用改动整个类层次。

       但是开闭原则的遵循有时也是片面的。如果系统中的类层次发生了变化,你必须修改访问者接口和每一个具体访问者。因此访问者模式适用于数据结构相对稳定的系统

       访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较合适的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统的数据结构对象易于变化,经常要有新的数据对象增加进来,就不适合使用访问者模式。

        总结一下,访问者模式适合处理集合中存在大量元素,且元素类型相对固定的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值