设计模式

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

2022-10-29  本文已影响0人  3d0829501918

  访问者模式在23种设计模式算是复杂的,因此在解释定义前,先以实际的例子代入一下,觉得理解起来会更好一些。

场景:很多人都有养宠物的习惯,这里就以此为例

访问者角色:给宠物喂食的人

具体访问者角色:主人、其他人

抽象元素角色:动物抽象类

具体元素角色:宠物狗、宠物猫

结构对象角色:主人家

结构图
interface Person {

     void feed(Cat cat);

     void feed(Dog dog);
}
class Owner implements Person {

@Override
public void feed(Cat cat) {
    System.out.println("主人喂食猫");
}

@Override
public void feed(Dog dog) {
    System.out.println("主人喂食狗");
}
}

class Someone implements Person {

@Override
public void feed(Cat cat) {
    System.out.println("其他人喂食猫");
}

@Override
public void feed(Dog dog) {
    System.out.println("其他人喂食狗");
}
}
interface Animal {
      void accept(Person person);
}
/**
 * 具体节点(元素)角色 -- 宠物狗
 */
class Dog implements Animal {

@Override
public void accept(Person person) {
    person.feed(this);
    System.out.println("好好吃,汪汪汪!!!");
}
}


/**
 * 具体节点(元素)角色 -- 宠物猫
 */
class Cat implements Animal {

@Override
public 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);
}

}

主人喂食狗
好好吃,汪汪汪!!!
主人喂食猫
好好吃,喵喵喵!!!
其他人喂食狗
好好吃,汪汪汪!!!
其他人喂食猫
好好吃,喵喵喵!!!

什么访问者模式?

  访问者模式(Visitor)表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为模式。

访问模式角色

  为该对象结构中的ConcreteElement的每一个类声明的一个操作。

  实现Visitor申明的每一个操作,每一个操作实现算法的一部分。

  它定义了一个接受访问者(accept)的方法,其意义是指,每一个元素都要可以被访问者访问。

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

  对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它会含有一组元素(Element),并且可以迭代这些元素,供访问者访问。

访问模式优缺点

优点:

 新增访问操作变得更加简单。

 能够使得用户在不修改现有类的层次结构下,定义该类层次结构的操作。

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

缺点:

 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背了“开闭原则”的要求。

 破坏封装。当采用访问者模式的时候,就会打破组合类的封装。

访问者模式结构图

访问者模式基本代码
public abstract class Visitor {

public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);

public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
public class ConcreteVisitor1 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
    System.out.println("ConcreteVisitor1:"+concreteElementA.operationA());
}

@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
    System.out.println("ConcreteVisitor1:"+concreteElementB.operationB());
}
}

public class ConcreteVisitor2 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
    System.out.println("ConcreteVisitor2:"+concreteElementA.operationA());
}

@Override
public 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 {
@Override
public void accept(Visitor visitor) {
    visitor.visitConcreteElementA(this);
}

public String operationA() {
    return "ConcreteElementA";
}
}

public class ConcreteElementB extends  Element {

@Override
public 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:ConcreteElementA
ConcreteVisitor1:ConcreteElementB
ConcreteVisitor2:ConcreteElementA
ConcreteVisitor2:ConcreteElementB

小结

  GoF四人中的一个作者说过:大多时候你并不需要访问者模式,但一旦你需要访问者模式时,那就是真的需要它了。事实上我们很难找到数据结构不变化的情况,所以用访问者模式的机会也就不太多了。


上一篇下一篇

猜你喜欢

热点阅读