访客设计模式是行为设计模式之一。当我们必须对一组类似的对象执行操作时,可以使用它。借助访问者模式,我们可以将操作逻辑从对象移动到另一个类。
null
访客模式由两部分组成:
- 一个名为 访问() 它由访问者实现,并为数据结构中的每个元素调用
- 可访问类提供 接受 接受访问者的方法
UML图访问者设计模式
设计组件
- 客户: 客户机类是访问者设计模式类的使用者。它可以访问数据结构对象,并可以指示它们接受访问者以执行适当的处理。
- 参观者: 这是一个接口或抽象类,用于声明所有类型的可访问类的访问操作。
- 访客: 对于每种类型的访问者,必须实现抽象访问者中声明的所有访问方法。每位访客将负责不同的操作。
- 可访问: 这是一个声明接受操作的接口。这是允许访问者对象“访问”对象的入口点。
- 具体可见: 这些类实现可访问接口或类,并定义接受操作。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