大话设计模式-访问者模式

引自原书

1.访问者模式适用于数据结构相对稳定的系统

2.它把数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化

3.访问者模式的目的是要把处理从数据结构分离出来

4.有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。

5.访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。

6.访问者的缺点就是使得增加新的数据结构变得困难了

大多数时候你并不需要访问者模式。我们很难找到数据结构不变化的情况

abstract class Action {
	//得到男人结论或反应
	public abstract function getManConclusion(Man $concreteElementA);


	//得到女人结论或反应
	public abstract function getWomanConclusion(Woman $concreteElementB);
}


abstract class Person {
	//接受(它是用来获得‘状态’对象的)
	public abstract function accept(Action $visitor);
}


//成功
class Success extends Action {
	public function getManConclusion(Man $concreteElementA) {
		echo get_class($concreteElementA).' '.get_class($this).'时,背后大多有一个伟大的女人。<br/>';
	}


	public function getWomanConclusion(Woman $concreteElementB) {
		echo get_class($concreteElementB).' '.get_class($this).'时,背后大多有一个不成功的男人。<br/>';
	}
}


//失败
class Failing extends Action {
	public function getManConclusion(Man $concreteElementA) {
		echo get_class($concreteElementA).' '.get_class($this).'时,闷头喝酒,谁也不用劝。<br/>';
	}


	public function getWomanConclusion(Woman $concreteElementB) {
		echo get_class($concreteElementB).' '.get_class($this).'时,眼泪汪汪,谁也劝不了。<br/>';
	}
}


//恋爱
class Amativeness extends Action {
	public function getManConclusion(Man $concreteElementA) {
		echo get_class($concreteElementA).' '.get_class($this).'时,凡事不懂也要装懂。<br/>';
	}


	public function getWomanConclusion(Woman $concreteElementB) {
		echo get_class($concreteElementB).' '.get_class($this).'时,遇事也装作不懂。<br/>';
	}
}

//结婚
class Marriage extends Action {
	public function getManConclusion(Man $concreteElementA) {
		echo get_class($concreteElementA).' '.get_class($this).'时,感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。<br/>';
	}


	public function getWomanConclusion(Woman $concreteElementB) {
		echo get_class($concreteElementB).' '.get_class($this).'时,欣慰曰:爱情长跑路漫漫,婚姻保险保平安。<br/>';
	}
}


//男人
class Man extends Person {
	public function accept(Action $visitor) {
		//首先在客户程序中将具体状态作为参数传递给‘男人’类完成了一次分派,然后‘男人’类调用作为参数的‘具体状态’中的方法‘男人反应’,同时将自己(this)作为参数传递进去。这便完成了第二次分派
		$visitor->getManConclusion($this);
	}
}


//女人
class Woman extends Person {
	public function accept(Action $visitor) {
		$visitor->getWomanConclusion($this);
	}
}


//对象结构
class ObjectStructure {
	private $elements;


	//增加
	public function attach(Person $element) {
		$this->elements[] = $element;
	}


	//移动
	public function detach(Person $element) {
		unset($this->elements[array_search($element, $this->elements)]);
	}


	//查看显示(遍历方法)
	public function display(Action $visitor) {
		foreach($this->elements as $e) {
			$e->accept($visitor);
		}
	}
}


$o = new ObjectStructure();
//在对象结构中加入要对比的‘男人’和‘女人’
$o->attach(new Man());
$o->attach(new Woman());


//成功时的反应
$v1 = new Success();
//查看在各种状态下,‘男人’和‘女人’的反应
$o->display($v1);


//失败时的反应
$v2 = new Failing();
$o->display($v2);


//恋爱时的反应
$v3 = new Amativeness();
$o->display($v3);


//结婚时的反应
$v4 = new Marriage();
$o->display($v4);


访问者模式

//为对象结构中ConcreteElement的每一个类声明一个Visit操作
abstract class Visitor {
	public abstract function visitConcreteElementA(ConcreteElementA $concreteElementA);
	public abstract function visitConcreteElementB(ConcreteElementB $concreteElementB);
}

//ConcreteVisitor1和ConcreteVisitor2类,具体访问者,实现每个由visitor声明的操作。每个操作实现算法的一部分,而该算法片断乃是对应于结构中对象的类。
class ConcreteVisitor1 extends Visitor {
	public function visitConcreteElementA(ConcreteElementA $concreteElementA) {
		echo get_class($concreteElementA).'被'.get_class($this).'访问1<br/>';
	}
	public function visitConcreteElementB(ConcreteElementB $concreteElementB) {
		echo get_class($concreteElementB).'被'.get_class($this).'访问1<br/>';
	}
}

class ConcreteVisitor2 extends Visitor {
	public function visitConcreteElementA(ConcreteElementA $concreteElementA) {
		echo get_class($concreteElementA).'被'.get_class($this).'访问2<br/>';
	}
	public function visitConcreteElementB(ConcreteElementB $concreteElementB) {
		echo get_class($concreteElementB).'被'.get_class($this).'访问2<br/>';
	}
}

//定义一个accept操作,它以一个访问者为参数。
abstract class Element {
	public abstract function Accept(Visitor $visitor);
}

//ConcreteElementA和ConcreteElementB类,具体元素,实现accept操作
class ConcreteElementA extends Element {
	//充分利用双分派技术,实现处理与数据结构的分离
	public function accept(Visitor $visitor) {
		$visitor->visitConcreteElementA($this);
	}
	//其他相关方法
	public function operationA(){
	}
}

class ConcreteElementB extends Element {
	//充分利用双分派技术,实现处理与数据结构的分离
	public function accept(Visitor $visitor) {
		$visitor->visitConcreteElementB($this);
	}
	//其他相关方法
	public function operationB(){
	}
}

//能枚举它的元素,可以提供一个高层的接口允许访问者访问它的元素。
class ObjectStructure {
	private $elements;

	public function attach(Element $element) {
		$this->elements[] = $element;
	}

	public function detach(Element $element) {
		$this->elements[] = $element;
	}

	public function accept(Visitor $visitor) {
		foreach($this->elements as $e) {
			$e->accept($visitor);
		}
	}
}

$o = new ObjectStructure();
$o->attach(new ConcreteElementA());
$o->attach(new ConcreteElementB());
$v1 = new ConcreteVisitor1();
$v2 = new ConcreteVisitor2();

$o->accept($v1);
$o->accept($v2);


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值