访客设计模式

访客设计模式是行为设计模式之一。当我们必须对一组类似的对象执行操作时,可以使用它。借助访问者模式,我们可以将操作逻辑从对象移动到另一个类。

null

访客模式由两部分组成:

  • 一个名为 访问() 它由访问者实现,并为数据结构中的每个元素调用
  • 可访问类提供 接受 接受访问者的方法

UML图访问者设计模式

Visitor-Design-Pattern-Diagram

设计组件

  • 客户: 客户机类是访问者设计模式类的使用者。它可以访问数据结构对象,并可以指示它们接受访问者以执行适当的处理。
  • 参观者: 这是一个接口或抽象类,用于声明所有类型的可访问类的访问操作。
  • 访客: 对于每种类型的访问者,必须实现抽象访问者中声明的所有访问方法。每位访客将负责不同的操作。
  • 可访问: 这是一个声明接受操作的接口。这是允许访问者对象“访问”对象的入口点。
  • 具体可见: 这些类实现可访问接口或类,并定义接受操作。visitor对象通过accept操作传递给这个对象。

让我们看看Java中访问者设计模式的一个例子。

interface ItemElement
{
public int accept(ShoppingCartVisitor visitor);
}
class Book implements ItemElement
{
private int price;
private String isbnNumber;
public Book( int cost, String isbn)
{
this .price=cost;
this .isbnNumber=isbn;
}
public int getPrice()
{
return price;
}
public String getIsbnNumber()
{
return isbnNumber;
}
@Override
public int accept(ShoppingCartVisitor visitor)
{
return visitor.visit( this );
}
}
class Fruit implements ItemElement
{
private int pricePerKg;
private int weight;
private String name;
public Fruit( int priceKg, int wt, String nm)
{
this .pricePerKg=priceKg;
this .weight=wt;
this .name = nm;
}
public int getPricePerKg()
{
return pricePerKg;
}
public int getWeight()
{
return weight;
}
public String getName()
{
return this .name;
}
@Override
public int accept(ShoppingCartVisitor visitor)
{
return visitor.visit( this );
}
}
interface ShoppingCartVisitor
{
int visit(Book book);
int visit(Fruit fruit);
}
class ShoppingCartVisitorImpl implements ShoppingCartVisitor
{
@Override
public int visit(Book book)
{
int cost= 0 ;
//apply 5$ discount if book price is greater than 50
if (book.getPrice() > 50 )
{
cost = book.getPrice()- 5 ;
}
else
cost = book.getPrice();
System.out.println( "Book ISBN::" +book.getIsbnNumber() + " cost =" +cost);
return cost;
}
@Override
public int visit(Fruit fruit)
{
int cost = fruit.getPricePerKg()*fruit.getWeight();
System.out.println(fruit.getName() + " cost = " +cost);
return cost;
}
}
class ShoppingCartClient
{
public static void main(String[] args)
{
ItemElement[] items = new ItemElement[]{ new Book( 20 , "1234" ),
new Book( 100 , "5678" ), new Fruit( 10 , 2 , "Banana" ),
new Fruit( 5 , 5 , "Apple" )};
int total = calculatePrice(items);
System.out.println( "Total Cost = " +total);
}
private static int calculatePrice(ItemElement[] items)
{
ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
int sum= 0 ;
for (ItemElement item : items)
{
sum = sum + item.accept(visitor);
}
return sum;
}
}


输出:

Book ISBN::1234 cost =20
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160

这里,在实现if accept()方法中,所有项都是相同的,但可以不同。例如,可以通过逻辑检查项目是否空闲,然后根本不调用visit()方法。

优势:

  • 如果操作逻辑发生了变化,那么我们只需要在visitor实现中进行更改,而不是在所有的item类中进行更改。
  • 向系统中添加一个新项目很容易,只需要更改访问者界面和实现,现有的项目类不会受到影响。

缺点:

  • 在设计时,我们应该知道visit()方法的返回类型,否则我们将不得不更改接口及其所有实现。
  • 如果访问者界面的实现太多,则很难扩展。

C++中访问者模式的另一个例子

//Write CPP code here
#include <iostream>
using namespace std;
class Stock
{
public :
virtual void accept( class Visitor *) = 0;
};
class Apple : public Stock
{
public :
/*virtual*/ void accept(Visitor *);
void buy()
{
cout << "Apple::buy" ;
}
void sell()
{
cout << "Apple::sell" ;
}
};
class Google : public Stock
{
public :
/*virtual*/ void accept(Visitor *);
void buy()
{
cout << "Google::buy" ;
}
void sell()
{
cout << "Google::sell" ;
}
};
class Visitor
{
public :
virtual void visit(Apple *) = 0;
virtual void visit(Google *) = 0;
//private:
static int m_num_apple, m_num_google;
void total_stocks()
{
cout << "m_num_apple " << m_num_apple
<< ", m_num_google " << m_num_google << '' ;
}
};
int Visitor::m_num_apple = 0;
int Visitor::m_num_google = 0;
class BuyVisitor : public Visitor
{
public :
BuyVisitor()
{
m_num_apple = m_num_google = 0;
}
/*virtual*/ void visit(Apple *r)
{
++m_num_apple;
r->buy();
cout << "m_num_apple " << m_num_apple << endl;
}
/*virtual*/ void visit(Google *b)
{
++m_num_google;
b->buy();
cout << " m_num_google " << m_num_google << '' ;
}
};
class SellVisitor : public Visitor
{
public :
/*virtual*/ void visit(Apple *a)
{
--m_num_apple;
a->sell();
cout << "m_num_apple " << m_num_apple << endl;
}
/*virtual*/ void visit(Google *g)
{
--m_num_google;
g->sell();
cout << "m_num_google " << m_num_google << endl;
}
};
void Apple::accept(Visitor *v)
{
v->visit( this );
}
void Google::accept(Visitor *v)
{
v->visit( this );
}
int main()
{
Stock *set[] = { new Apple, new Google, new Google,
new Apple, new Apple, 0 };
BuyVisitor buy_operation;
SellVisitor sell_operation;
for ( int i = 0; set[i]; i++)
{
set[i]->accept(&buy_operation);
}
buy_operation.total_stocks();
for ( int i = 0; set[i]; i++)
{
set[i]->accept(&sell_operation);
}
sell_operation.total_stocks();
}


输出:

Apple::buy
m_num_apple 1
Google::buy
 m_num_google 1
Google::buy
 m_num_google 2
Apple::buy
m_num_apple 2
Apple::buy
m_num_apple 3
m_num_apple 3, m_num_google 2
Apple::sell
m_num_apple 2
Google::sell
m_num_google 1
Google::sell
m_num_google 0
Apple::sell
m_num_apple 1
Apple::sell
m_num_apple 0
m_num_apple 0, m_num_google 0

本文由 萨凯特·库马尔 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享