文档章节

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

行走的螃蟹
 行走的螃蟹
发布于 2014/08/15 16:28
字数 1265
阅读 64
收藏 0

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


© 著作权归作者所有

行走的螃蟹

行走的螃蟹

粉丝 33
博文 48
码字总数 23634
作品 0
杭州
程序员
私信 提问
加载中

评论(1)

Yi_Zhi_Yu
Yi_Zhi_Yu
感觉你这个更像是策略模式
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
2018/11/06
185
0
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
296
0
PHP设计模式(一):简介及创建型模式

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设...

juhenj
2014/05/15
286
2
设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信
2018/03/22
0
0
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
5
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
8
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
12
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
16
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部