补-计划模式之访问者模式(十三)

开发者 2024-10-6 20:17:12 91 0 来自 中国
  访问者模式在23种计划模式算是复杂的,因此在表明界说前,先以实际的例子代入一下,以为明确起来会更好一些。
场景:许多人都有养宠物的风俗,这里就以此为例
访问者角色:给宠物喂食的人
具体访问者角色:主人、其他人
抽象元素角色:动物抽象类
具体元素角色:宠物狗、宠物猫
结构对象角色:主人家
2.jpg

  • 创建抽象访问者接口
interface Person {     void feed(Cat cat);     void feed(Dog dog);}

  • 创建差别的具体访问者角色 -- 主人/其他人,同时实现Person接口
class Owner implements Person {@Overridepublic void feed(Cat cat) {    System.out.println("主人喂食猫");}@Overridepublic void feed(Dog dog) {    System.out.println("主人喂食狗");}}class Someone implements Person {@Overridepublic void feed(Cat cat) {    System.out.println("其他人喂食猫");}@Overridepublic void feed(Dog dog) {    System.out.println("其他人喂食狗");}}

  • 创建 抽象节点 -- 宠物
interface Animal {      void accept(Person person);}

  • 创建实现Animal接口的 具体节点(元素)
/** * 具体节点(元素)角色 -- 宠物狗 */class Dog implements Animal {@Overridepublic void accept(Person person) {    person.feed(this);    System.out.println("好好吃,汪汪汪!!!");}}/** * 具体节点(元素)角色 -- 宠物猫 */class Cat implements Animal {@Overridepublic void accept(Person person) {    person.feed(this);    System.out.println("好好吃,喵喵喵!!!");}}

  • 创建结构对象角色
class Home {private List<Animal> nodeList = new ArrayList<>();void action(Person person) {    for (Animal node : nodeList) {        node.accept(person);    }}/** * 添加操纵 * * @param animal 动物 */void add(Animal animal) {    nodeList.add(animal);}}

  • 创建客户端,用于测试
public class Client {public static void main(String[] args) {    Home home = new Home();    home.add(new Dog());    home.add(new Cat());    Owner owner = new Owner();    home.action(owner);    Someone someone = new Someone();    home.action(someone);}}

  • 运行结果
主人喂食狗好好吃,汪汪汪!!!主人喂食猫好好吃,喵喵喵!!!其他人喂食狗好好吃,汪汪汪!!!其他人喂食猫好好吃,喵喵喵!!!
4.jpg
  访问者模式(Visitor)表现一个作用于某对象结构中的各元素的操纵。它使你可以在不改变各元素的类的条件下界说作用于这些元素的新操纵。访问者模式是一种对象活动模式。

5.jpg

  • Visitor 抽象访问者
  为该对象结构中的ConcreteElement的每一个类声明的一个操纵。

  • ConcreteVisitor 具体访问者
  实现Visitor阐明的每一个操纵,每一个操纵实现算法的一部分。

  • Element  抽象元素
  它界说了一个继承访问者(accept)的方法,其意义是指,每一个元素都要可以被访问者访问。

  • ConcreteElement 具体元素
  它提供继承访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。

  • ObjectStructure 对象结构角色
  对象结构是一个抽象表述,具体点可以明确为一个具有容器性子大概复合对象特性的类,它会含有一组元素(Element),而且可以迭代这些元素,供访问者访问。

8.jpg
优点:
 新增访问操纵变得更加简朴。
 可以或许使得用户在不修改现有类的条理结构下,界说该类条理结构的操纵。
 将有关元素对象的访问活动会合到一个访问者对象中,而不是分散搞一个个的元素类中。
缺点:
 增长新的元素类很困难。在访问者模式中,每增长一个新的元素类都意味着要在抽象访问者角色中增长一个新的抽象操纵,并在每一个具体访问者类中增长相应的具体操纵,违反了“开闭原则”的要求。
 粉碎封装。当接纳访问者模式的时候,就会突破组合类的封装。





  • 抽象访问者
public abstract class Visitor {public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);}

  • 具体访问者
public class ConcreteVisitor1 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {    System.out.println("ConcreteVisitor1:"+concreteElementA.operationA());}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {    System.out.println("ConcreteVisitor1:"+concreteElementB.operationB());}}public class ConcreteVisitor2 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {    System.out.println("ConcreteVisitor2:"+concreteElementA.operationA());}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {    System.out.println("ConcreteVisitor2:"+concreteElementB.operationB());}}

  • 抽象元素
public abstract class Element {       public abstract void accept(Visitor visitor);}

  • 具体元素
public class ConcreteElementA extends Element {@Overridepublic void accept(Visitor visitor) {    visitor.visitConcreteElementA(this);}public String operationA() {    return "ConcreteElementA";}}public class ConcreteElementB extends  Element {@Overridepublic void accept(Visitor visitor) {    visitor.visitConcreteElementB(this);}public String operationB() {    return "ConcreteElementB";}}

  • 对象结构角色
public class ObjectStructure {private List<Element> elments = new LinkedList<Element>();// 新增public void attach(Element element) {    elments.add(element);}// 删除public void detach(Element element) {    elments.remove(element);}public  void accept(Visitor visitor) {    for (Element elment:elments ) {        elment.accept(visitor);    }}}

  • 测试类
public class Test {public static void main(String[]args) {    ObjectStructure o = new ObjectStructure();    o.attach(new ConcreteElementA());    o.attach(new ConcreteElementB());    ConcreteVisitor1 concreteVisitor1 = new ConcreteVisitor1();    ConcreteVisitor2 concreteVisitor2 = new ConcreteVisitor2();    o.accept(concreteVisitor1);    o.accept(concreteVisitor2);}}

  • 运行结果
ConcreteVisitor1:ConcreteElementAConcreteVisitor1:ConcreteElementBConcreteVisitor2:ConcreteElementAConcreteVisitor2:ConcreteElementB

  GoF四人中的一个作者说过:大多时候你并不必要访问者模式,但一旦你必要访问者模式时,那就是真的必要它了。究竟上我们很难找到数据结构稳固革的情况,所以用访问者模式的机遇也就不太多了。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-12-4 02:00, Processed in 0.194404 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表