您的位置:首页 > 其它

再探设计模式之访问者模式

2015-09-03 14:51 197 查看
访问者模式的使用条件比较苛刻

主要可以以用于新增访问者时只需要新增一个访问者类,原有代码无需修改,增加一个被访问者时只需增加一个访问方法并在具体访问者中实现,源码同样不需要改变,符合开闭原则

通过访问者和被访问者集中到对象结构供访问者访问的方式使得类的职责更加明确,同一个结构对象可供多个访问者访问,实现代码的复用

package com.linewell.modeldesign.visitor

/**
 * 某公司欲为某高校开发一套奖励审批系统,该系统可以实现教师奖励和学生奖励的审批
 * 如果教师发表论文超过10篇或者学生发表论文超过2篇,就可以评科研奖
 * 如果教师教学反馈分大于90分或者学生平时成绩大于90分就可以评选成绩优秀奖
 * 判断集合内的教师或者学生是否符合获奖要求
 * Created by ctao on 2015/9/2.
 *
 *
 * 设计思路:
 * 可以采用访问者模式
 * 奖励审批过程其实可以将奖项看成访问者,将角色看作被访问者,将角色加入角色队列,对每一个角色进行访问
 * 所以一共可以抽象出抽象被访问者:人物类,具体被访问者:学生类和老师类
 * 抽象访问者:奖项类,具体访问者:科研奖项和成绩优秀奖项
 * 对象结构:角色类集合
 */

/**
 * 人物类:抽象被访问者
 * @param name 姓名
 */
sealed abstract class Person(val name: String) {
    def applyAward(award: Award)
}

/**
 * 学生,具体角色
 * @param name 姓名
 * @param thesisNum 论文数
 * @param testScore 平时成绩
 */
case class Student(override val name: String, thesisNum: Int, testScore: Double) extends Person(name) {
    override def applyAward(award: Award): Unit = award.judge(this)
}

/**
 * 老师,具体角色
 * @param name 姓名
 * @param thesisNum 论文数
 * @param feedbackScore 反馈分数
 */
case class Teacher(override val name: String, thesisNum: Int, feedbackScore: Double) extends Person(name) {
    override def applyAward(award: Award): Unit = award.judge(this)
}

package com.linewell.modeldesign.visitor

/**
 * 奖项:访问者
 * Created by ctao on 2015/9/3.
 */
sealed trait Award {
    /**
     * 评选方法:原有做法
     * 问题是如果此时面向抽象对象编程那么增加一个新的角色将修改原来的代码,不符合开闭原则
     * 所以在这里应该面对具体人物编程
     * def judge(person: Person)
     * 如果此时增加一个奖项那就增加一个类
     * 如果此时增加一个角色,那么就增加一个评选方法
     * 原有代码不需要修改
     **/
    /**
     * 对学生的评选
     * @param person 学生
     */
    def judge(person: Student): Unit

    /**
     * 对老师的评选
     * @param person 老师
     */
    def judge(person: Teacher): Unit

}

/**
 * 将定义的子奖项放入奖项的伴生对象
 * 就可以实现封装
 */
object Award {
    /**
     * 简单工厂
     * @param award 奖项名
     * @return 奖项子对象
     */
    def apply(award: String) = award match {
        case a if a.equalsIgnoreCase("PerformanceAward") => PerformanceAward
        case a if a.equalsIgnoreCase("ResearchAward") => ResearchAward
        case _ => Thread sleep 1
            throw new ClassNotFoundException("没有该奖项")

    }

    /**
     * 成绩优秀奖项:具体访问者
     */
    case object PerformanceAward extends Award {
        /**
         * 原有做法
         * override def judge(person: Person): Unit = person match {
         * case p if p.isInstanceOf[Student] => val student = p.asInstanceOf[Student]
         * student.testScore match {
         * case score if score > 90 => println(s"恭喜${student.name}同学获得成绩优秀奖")
         * case _ => println(s"很遗憾,${student.name}同学在本次成绩优秀奖项的评选中落选了")
         * }
         *
         * case p if p.isInstanceOf[Teacher] => val teacher = p.asInstanceOf[Teacher]
         * teacher.feedbackScore match {
         * case score if score > 90 => println(s"恭喜${teacher.name}老师获得成绩优秀奖")
         * case _ => println(s"很遗憾,${teacher.name}老师在本次成绩优秀奖项的评选中落选了")
         * }
         * }
         */

        /**
         *
         * @param person 学生
         */
        override def judge(person: Student): Unit = person.testScore match {
            case score if score > 90 => println(s"恭喜${person.name}同学获得成绩优秀奖")
            case _ => println(s"很遗憾,${person.name}同学在本次成绩优秀奖项的评选中落选了")
        }

        /**
         *
         * @param person 老师
         */
        override def judge(person: Teacher): Unit = person.feedbackScore match {
            case score if score > 90 => println(s"恭喜${person.name}老师获得成绩优秀奖")
            case _ => println(s"很遗憾,${person.name}老师在本次成绩优秀奖项的评选中落选了")
        }
    }

    /**
     * 科研奖项:具体访问者
     */
    case object ResearchAward extends Award {
        /**
         * 原有做法
         * override def judge(person: Person): Unit = person match {
         * case p if p.isInstanceOf[Student] => val student = p.asInstanceOf[Student]
         * student.thesisNum match {
         * case num if num > 2 => println(s"恭喜${student.name}同学获得科研奖")
         * case _ => println(s"很遗憾,${student.name}同学在本次科研奖项的评选中落选了")
         * }
         * case p if p.isInstanceOf[Teacher] => val teacher = p.asInstanceOf[Teacher]
         * teacher.thesisNum match {
         * case num if num > 10 => println(s"恭喜${teacher.name}老师获得科研奖")
         * case _ => println(s"很遗憾,${teacher.name}老师在本次科研奖项的评选中落选了")
         * }
         *
         * }
         */

        /**
         *
         * @param person 学生
         */
        override def judge(person: Student): Unit = person.thesisNum match {
            case num if num > 2 => println(s"恭喜${person.name}同学获得科研奖")
            case _ => println(s"很遗憾,${person.name}同学在本次科研奖项的评选中落选了")
        }

        /**
         *
         * @param person 老师
         */
        override def judge(person: Teacher): Unit = person.thesisNum match {
            case num if num > 10 => println(s"恭喜${person.name}老师获得科研奖")
            case _ => println(s"很遗憾,${person.name}老师在本次科研奖项的评选中落选了")
        }
    }

}

package com.linewell.modeldesign.visitor

import scala.collection.mutable.ArrayBuffer

/**
 * 对象集合类
 * Created by ctao on 2015/9/3.
 */
class PersonBuffer {
    /**
     * 存放需要参加评选的人物
     */
    private var persons = new ArrayBuffer[Person]()

    /**
     * 添加需要评选的人物
     * @param person 人物
     */
    def addPerson(person: Person) = person match {
        case p if persons.exists(p.eq(_)) => println(s"${p.name}已经在评选组内,不要重复申请")
        case _ => persons += person
    }

    def applyAward(award: Award) = persons.foreach(_.applyAward(award))
}

package com.linewell.modeldesign.visitor

/**
 * 访问者模式测试客户端
 * Created by ctao on 2015/9/3.
 */
object Client extends App {
    /**
     * 人物
     */
    val ct: Person = Student("ct", 8, 91)
    val pk: Person = Student("pk", 2, 70)
    val cwy: Person = Student("cwy", 3, 66)
    val wkl: Person = Student("wkl", 1, 80)
    val wzh: Person = Teacher("wzh", 11, 88)
    val kmj: Person = Teacher("kmj", 5, 91)

    /**
     * 对象结构
     */
    val personBuffer = new PersonBuffer
    /**
     * 添加评选对象
     */
    personBuffer.addPerson(ct)
    personBuffer.addPerson(ct)
    personBuffer.addPerson(pk)
    personBuffer.addPerson(cwy)
    personBuffer.addPerson(wkl)
    personBuffer.addPerson(wzh)
    personBuffer.addPerson(kmj)

    /**
     * 成绩优秀奖的评选
     */
    val performance = Award("PerformanceAward")

    personBuffer.applyAward(performance)

    /**
     * 科研奖的评选
     */
    val research= Award("ResearchAward")
    personBuffer.applyAward(research)
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: