设计模式之访问者模式

来源:互联网 发布:nodejs获取windows ip 编辑:程序博客网 时间:2024/05/06 12:53

为什么要使用访问者设计模式?

先看一下下面这段代码

class Person{private String action ;private String name;public Person(String name){this.name = name;}public String getAction() {return action;}public void setAction(String action) {this.action = action;}public void getConclusion(){if(action == "Happy"){System.out.println(name+" feel "+"Happy");}else if(action == "Exciting"){System.out.println(name+" feel "+"Exciting");}else if(action == "Grieved"){System.out.println(name+" feel "+"Grieved");}}}public class Client {public static void main(String [] args){Person person = new Person("jeason");person.setAction("Happy");person.getConclusion();}}

如果需要添加一种feeling那么需要去改动Person类,这里违背了开放封闭原则,getConclusion()需要对每种feeling都分别做操作,这里违背了单一职责原则.现在我们利用访问者模

式就可以就可以避免违反的两种原则.

什么是访问者设计模式?

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

涉及角色
1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口。
3.Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
4.ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
5.ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
访问者模式的几个特点:
访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。

怎么使用访问者设计模式?

我们根据之前的需求和访问者模式的概念设计出UML:

具体代码:

State.class

public abstract class State {public abstract void eflectPerson(Person person);}

Happy.class

public class Happy extends State{@Overridepublic void eflectPerson(Person person) {// TODO Auto-generated method stubSystem.out.println(person.getName()+" feel happy");}}

Grieved.class

public class Grieved extends State{@Overridepublic void eflectPerson(Person person) {// TODO Auto-generated method stubSystem.out.println(person.getName()+" feel grieved");}}

Exciting.class

public class Exciting extends State{@Overridepublic void eflectPerson(Person person) {// TODO Auto-generated method stubSystem.out.println(person.getName()+" feel exciting");}}

Person.class

public class Person {private String name;public Person(String name){this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}//双分派public void receiveState(State state){state.eflectPerson(this);}}

这里解释一下什么叫双分派:假设有A,B两个对象,对象A中有一个方法需要用到对象B的引用,而在这个方法中去调用对象B的方法会用到对象A的引用。它使得执行结果不仅取决

于B类而且还取决于A类.

PersonStructure.class

public class PersonStructure {private ArrayList<Person> arrayList = new ArrayList<Person>();public void addPerson(Person person){arrayList.add(person);}public void remove(Person person){arrayList.remove(person);}public void displayPersonName(){for(Person p : arrayList){System.out.println("person name "+p.getName());}}public void receiveState(State state){for(Person p : arrayList){p.receiveState(state);}}}

Client.class

public class Client {public static void main(String [] args){Person p1 = new Person("jeason");Person p2 = new Person("neo");Person p3 = new Person("kuku");PersonStructure personStructure = new PersonStructure();personStructure.addPerson(p1);personStructure.addPerson(p2);personStructure.addPerson(p3);personStructure.displayPersonName();personStructure.receiveState(new Happy());}}

最后输出:

person name jeason
person name neo
person name kuku
jeason feel happy
neo feel happy
kuku feel happy

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 海淘地址试投不成功怎么办 怀孕了吐得厉害怎么办 玩网页游戏好卡怎么办 网页游戏占cpu高怎么办 微信有余额绑定其他名下怎么办 银行卡绑定支付余额不对怎么办 可乐机不制冷了怎么办 被淘宝卖家威胁怎么办 征信不好想贷款怎么办 急用钱征信不好怎么办 急用钱逾期不还怎么办 急用钱借款不还怎么办 做b超按压疼痛怎么办 做b超没有尿怎么办 b超憋不到尿怎么办 做b超前没有尿意怎么办 肝胆b超前喝水了怎么办 肝胆彩超喝水了怎么办 胆囊b超喝了水怎么办 系统b超照不到怎么办 思维彩超宝宝不动怎么办 怀孕七个月胎儿缺氧怎么办 怀孕29周小孩偏小怎么办 孕29周胎儿臀位怎么办 刚怀孕有囊肿该怎么办 食杏中毒怎么办吃什么 猫吃了扁桃仁怎么办 夏天来了??点狐臭怎么办? 我有一小点狐臭怎么办 淘客网站被微信屏蔽怎么办 微信老是屏蔽网站怎么办 华帝售后没人理怎么办 新开的网店没生意怎么办 淘小二介入买家举证不全怎么办 新股申购中签后钱不够怎么办 买的东西收不到怎么办? 拼多多按错收货怎么办 团购招生做到一半不如意怎么办 网购付款后卖家没有货怎么办 淘宝退货商家不同意退款怎么办 淘宝确认收货后卖家拒绝退款怎么办