android设计模式二十三式(二十一)——访问者模式(Visitor)

访问者模式

访问者模式,主要的作用就是把数据结构和针对数据结构上的操作进行解耦,适用于数据结构稳定,但是针对数据的操作容易变化的场景,访问者模式,改变操作数据的方法容易,但是改变数据结构困难,如果数据结构经常变化,则不能使用此模式

先来确定一下访问者模式的组成

被访问者接口:提供接收访问方法

被访问者:接收访问,将自己的提供给访问者,自己的结构不易变化

访问者接口:提供不同的访问方法

访问者:访问数据,对针对数据的结构有不同的造作。

 

我们还是来举个栗子:

每个员工都有工龄和工资,公司按照工龄来计算工资,社保局根据工资和工龄来计算是否符合退休条件以及退休工资

这里抽象一个员工接口,接收访问

具体一个人实现接口,包含姓名,工龄,工资

再抽象一个机构接口,可以访问员工的信息

公司和社保局实现机构接口,处理自己的逻辑。

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: Org
 */
public interface Org {
    void visit(Person person);
}

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: employee
 */
public interface employee {
    void accept(Org org);
}

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: Person
 */
public class Person implements employee {
    private String name;
    private int  workingAge;
    private double salary;

    public Person(String name, int workingAge, double salary) {
        this.name = name;
        this.workingAge = workingAge;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWorkingAge() {
        return workingAge;
    }

    public void setWorkingAge(int workingAge) {
        this.workingAge = workingAge;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public void accept(Org org) {
        org.visit(this);
    }
}

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: Company
 */
public class Company implements Org {

    @Override
    public void visit(Person person) {
        if (person.getWorkingAge() > 5){
            System.out.println(person.getName()+"当前薪资"+person.getSalary()+",涨薪100");
        }else if (person.getWorkingAge() > 10){
            System.out.println(person.getName()+"当前薪资"+person.getSalary()+",涨薪500");
        }else{
            System.out.println(person.getName()+"当前薪资"+person.getSalary()+",不涨薪");
        }
    }
}

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: SocialSecurityBureau
 */
public class SocialSecurityBureau implements Org {

    @Override
    public void visit(Person person) {
        if (person.getWorkingAge() < 15) {
            System.out.println(person.getName()+"不符合退休条件");
        }else {
            System.out.println(person.getName()+"退休工资为:"+(person.getWorkingAge()*10 + person.getSalary()*0.8));
        }
    }
}

来看一下怎么访问

public static void main(String[] args){
    Person person1 = new Person("小明",3,3000D);
    Person person2 = new Person("小红",6,5000D);
    Person person3 = new Person("小张",11,8000D);
    Person person4 = new Person("小王",16,10000D);

    person1.accept(new Company());
    person1.accept(new SocialSecurityBureau());
    person2.accept(new Company());
    person2.accept(new SocialSecurityBureau());
    person3.accept(new Company());
    person3.accept(new SocialSecurityBureau());
    person4.accept(new Company());
    person4.accept(new SocialSecurityBureau());
}

输出结果:
小明当前薪资3000.0,不涨薪
小明不符合退休条件
小红当前薪资5000.0,涨薪100
小红不符合退休条件
小张当前薪资8000.0,涨薪100
小张不符合退休条件
小王当前薪资10000.0,涨薪100
小王退休工资为:8160.0

功能已经实现,但是可以看到,调用的时候特别麻烦,也可以看到,在实际调用的时候,组织的实现类不能调用接口,所以,访问者模式是不符合依赖倒转原则的。所以才会有对数据结构的稳定性有要求。

上面的调用其实也可以一个管理类中集中管理起来

/**
 * @author: hx
 * @Time: 2019/5/23
 * @Description: People
 */
public class People {
    private List<Person> mPeople = new ArrayList<>();

    public void addPerson(Person person){
        mPeople.add(person);
    }

    public void accept(Org org){
        for (Person person : mPeople){
            person.accept(org);
        }
    }
}

再看一下调用

public static void main(String[] args){
    Person person1 = new Person("小明",3,3000D);
    Person person2 = new Person("小红",6,5000D);
    Person person3 = new Person("小张",11,8000D);
    Person person4 = new Person("小王",16,10000D);

    People people = new People();
    people.addPerson(person1);
    people.addPerson(person2);
    people.addPerson(person3);
    people.addPerson(person4);

    people.accept(new Company());
    people.accept(new SocialSecurityBureau());
}

输出结果:
小明当前薪资3000.0,不涨薪
小红当前薪资5000.0,涨薪100
小张当前薪资8000.0,涨薪100
小王当前薪资10000.0,涨薪100
小明不符合退休条件
小红不符合退休条件
小张不符合退休条件
小王退休工资为:8160.0

比第一种稍稍好一点

优点

  增加新的访问操作十分方便

       每个访问者类的职责更加清晰

  将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,集中管理

缺点

  增加新的元素类很困难,违背了开闭原则

       访问者访问的是实现类而不是接口,违背了依赖倒转原则

应用场景

  一个对象结构包含多个类型的对象,对这些对象的造作依赖具体实现。 不同的类型可以有不同的访问操作

  数据结构对象结构不会改变,但经常需要在此对象结构上定义新的操作。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值