螃蟹学PHP设计模式之访问者模式

原创
2014/08/15 16:28
阅读数 64

17.访问者模式

貌似这是螃蟹学的最后一个设计模式了,可能还有其他的,不过常用的也够了。所谓访问者设计模式,其实也好理解,就是通过访问者实现访对象的访问和处理。就像我计划要去旅游,好多国家都想去,但是我可能是一次游完,最佳就是一次去一个好好玩一下。访问者设计模式在于对象的功能处理,不需要全部定义在原对象里,而是拆分处理,便于更多的开发者参与进来,也可以很好拓展。

参考项目模块:商品排序

由于商品对象是固定的,但经常要对商品进行不同的排序,而不同的排序得出的商品列表格式都是相同的,那么使用访问者设计模式来实现对商品的处理就是很好的方式。这里螃蟹再次尝试用新的方式来实现商品排序。

商品对象:Goods.class.php

<?php 

class Goods{
	public $title = '';
	public $price = 0;
	public $distance = 0;
	
	public function __construct($goods){
		$this->title = $goods['title'];
		$this->price = $goods['price'];
		$this->distance = $goods['distance'];
	}

	public function getArray(){
		return array('title'=>$this->title,'price'=>$this->price,'distance'=>$this->distance);
	}
	
}

?>



商品集合对象:GoodsList.class.php

<?php 
require_once('Goods.class.php');

class GoodsList{
	public $goods_objs = '';
	public $goods_array = '';
	
	public function __construct(){
		$this->goods_objs = array();
		$this->goods_array = array();
	}
	
	public function addGoods(Goods $goods){
		array_push($this->goods_objs, $goods);
		array_push($this->goods_array, $goods->getArray());
	}
	
	public function getDefaultList(){
		foreach ($this->goods_objs as $goods){
			echo '	      商品名:'.$goods->title;
			echo '    价格:'.$goods->price;
			echo '    距离:'.$goods->distance;
			echo '<br><br>';
		}
	}
	
	public function getOrderList(){
		foreach ($this->goods_array as $goods){
			echo '    商品名:'.$goods['title'];
			echo '    价格:'.$goods['price'];
			echo '    距离:'.$goods['distance'];
			echo '<br><br>';
		}
	}
	
	public function getVisitor($visitor,$sortType='ASC'){
		if($sortType=='ASC'){
			$this->goods_array = $visitor->AscSort($this->goods_array);
		}else{
			$this->goods_array = $visitor->DescSort($this->goods_array);
		}
	}
	
}

?>



在集合对象里面定义了排序相关的访问者方法,通过此方法去调用访问者对象。

价格排序访问类:PriceSort.visitor.php

<?php 
require_once('Sort.fun.php');

class PriceSort{
	public function AscSort($goodslist){
		return SortFun::subSort($goodslist, 'price','ASC');		
	}

	public function DescSort($goodslist){
		return SortFun::subSort($goodslist, 'price','DESC');
	}
}
?>



距离排序访问类:DistanceSort.visitor.php

<?php 
require_once('Sort.fun.php');

class DistanceSort{
	public function AscSort($goodslist){
		return SortFun::subSort($goodslist, 'distance','ASC');
	}

	public function DescSort($goodslist){
		return SortFun::subSort($goodslist, 'distance','DESC');
	}
}
?>



然后写个功能类,里面自定义一个二维数组排序算法:Sort.fun.php

<?php 
class SortFun{
	//二维数组排序算法
	public static function subSort($arr,$keys,$type='ASC'){
		$keysvalue = $new_array = array();
		foreach ($arr as $k=>$v){
			$keysvalue[$k] = $v[$keys];
		}
		if($type == 'ASC'){
			asort($keysvalue);
		}else{
			arsort($keysvalue);
		}
		reset($keysvalue);
		$i=0;
		foreach ($keysvalue as $k=>$v){
			$new_array[$i] = $arr[$k];
			$i++;
		}
		return $new_array;
	}
	
}

?>



最后编写测试文件:TestVisitor.php

<?php 
function __autoload($className){
	if(file_exists($className.'.class.php')){
		require_once($className.'.class.php');
	}
	if(file_exists($className.'.visitor.php')){
		require_once($className.'.visitor.php');
	}
}

//模拟商品数据
$goods = array();
$goods[0] = array('title'=>'六神花露水','price'=>12.99,'distance'=>3.04);
$goods[1] = array('title'=>'七神花露水','price'=>10.99,'distance'=>1.14);
$goods[2] = array('title'=>'八神花露水','price'=>8.99,'distance'=>5.24);
$goods[3] = array('title'=>'九神花露水','price'=>23.29,'distance'=>0.74);
$goods[4] = array('title'=>'十神花露水','price'=>1.99,'distance'=>13.64);

//添加到商品集合
$goodsLists = new GoodsList();
foreach ($goods as $goodsData){
	$goodsobj = new Goods($goodsData);
	$goodsLists->addGoods($goodsobj); 	
}

echo '<h3>正常输出</h3>';
$goodsLists->getDefaultList();

echo '<h3>按价格从高到低</h3>';
$goodsLists->getVisitor(new PriceSort(),'DESC');
$goodsLists->getOrderList();

echo '<h3>按价格从低到高</h3>';
$goodsLists->getVisitor(new PriceSort(),'ASC');
$goodsLists->getOrderList();

echo '<h3>按距离从近到远</h3>';
$goodsLists->getVisitor(new DistanceSort(),'ASC');
$goodsLists->getOrderList();

?>



测试结果:

正常输出

商品名:六神花露水 价格:12.99 距离:3.04

商品名:七神花露水 价格:10.99 距离:1.14

商品名:八神花露水 价格:8.99 距离:5.24

商品名:九神花露水 价格:23.29 距离:0.74

商品名:十神花露水 价格:1.99 距离:13.64

按价格从高到低

商品名:九神花露水 价格:23.29 距离:0.74

商品名:六神花露水 价格:12.99 距离:3.04

商品名:七神花露水 价格:10.99 距离:1.14

商品名:八神花露水 价格:8.99 距离:5.24

商品名:十神花露水 价格:1.99 距离:13.64

按价格从低到高

商品名:十神花露水 价格:1.99 距离:13.64

商品名:八神花露水 价格:8.99 距离:5.24

商品名:七神花露水 价格:10.99 距离:1.14

商品名:六神花露水 价格:12.99 距离:3.04

商品名:九神花露水 价格:23.29 距离:0.74

按距离从近到远

商品名:九神花露水 价格:23.29 距离:0.74

商品名:七神花露水 价格:10.99 距离:1.14

商品名:六神花露水 价格:12.99 距离:3.04

商品名:八神花露水 价格:8.99 距离:5.24

商品名:十神花露水 价格:1.99 距离:13.64



可以看到商品排序很方便,而且结构很清晰。如果后面要添加按时间,按浏览量,按购买量排序都很好拓展,即便不同的程序员来开发,按照这种定义方式也是很容易上手的。

PHP的设计到这里就告一段落了,螃蟹也感觉收货不少,面向对象的很多概念又重温了一遍,后面肯定会在项目中尝试使用各种设计模式,提高项目的质量,也算是提高螃蟹自身的价值吧。好吧,还有一会下班,周末愉快~~


展开阅读全文
打赏
1
0 收藏
分享
加载中
感觉你这个更像是策略模式
2014/10/16 11:13
回复
举报
更多评论
打赏
1 评论
0 收藏
1
分享
返回顶部
顶部