PHP工厂模式

没有评论

2011 年 08 月 31 日 at 下午 11:33分类:PHP

工厂类是指包含一个专门用来创建其他对象的方法的类,工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活,熟练掌握工厂模式高级PHP开发人员是很重要的。
工厂模式通常用来返回符合类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者,从而允许我们基于应用程序逻辑或者配置设置来决定应实例化哪一个类,例如,可以使用这样的提供者来扩展一个类,而不需要重构应用程序的其他部分,从而使用新的扩展后的名称 。

通常,工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,工厂方法可以任意命名,这个静态还可以接受任意数据的参数,必须返回一个对象。

abstract class Calculator
        {
        	private $number1;
        	private $number2;
        	public $result;
			/**
	 * @return the $number2
	 */
	public function getNumber2() {
		return $this->number2;
	}

			/**
	 * @param field_type $number2
	 */
	public function setNumber2($number2) {
		$this->number2 = $number2;
	}

	/**
	 * @return the $number1
	 */
	public function getNumber1() {
		return $this->number1;
	}

			/**
	 * @param field_type $number1
	 */
	public function setNumber1($number1) {
		$this->number1 = $number1;
	}
	
	abstract function get_result();
 }
        
 class Add extends Calculator
	{
		public function get_result($number1,$number2)
		{
			return $number1+$number2;
		}
	}
	
class Sub extends Calculator
	{
		public function get_result($number1,$number2)
		{
			return $number1-$number2;
		}
	}
	
class Mul extends Calculator
	{
		public function get_result($number1,$number2)
		{
			return $number1*$number2;
		}
	}
	
class Div extends Calculator
	{
		public function get_result($number1,$number2)
		{
			return $number1/$number2;
		}
	}

//工厂实现类	
class Factory
	{
		public function Building($notes)
		{
			if($notes=="+")
			{
				$add=new Add();
				return $add;
			}
			elseif ($notes=="-")
			{
				$sub=new Sub();
				return $sub;
			}
			elseif($notes=="*")
			{
				$mul=new Mul();
				return $mul;
			}
			else
			{
				$div=new Div();
				return $div;
			}
		}
	}

个人最浅显易懂的理解:有一个类(工厂类),它只返回其他类的实例,而这个实例是根据这类在调用工厂方法的时候的的参数来指定要实例化哪个类,从而反悔该指定类的对象。

PHP单例模式

没有评论

2011 年 08 月 31 日 at 下午 11:01分类:PHP

模式对于OOP开发人员尤其有用,因为他有助于创建稳定的API,并且仍然保持一定的灵活度。一种模式可以帮助我们定义负责完成特定任务的对象,还可以允许我们全部修改掉某个类而不用修改与这些类打交道的代码。前者被称为类的职责,后者被称为类的多态性。
单例模式被当作职责模式,他用来在应用程序中创建一个单一的功能访问点。它将创建对象的控制权委托到一个单一的 访问点上。在任何时候,应用程序中都只会有这个类仅有的一个实例存在。这可以防止我们去打开数据库的多个连接或者不必要得使用多余的系统资源。在更加复杂 的系统中,使用单例模式在维持应用程序状态的同步方面也尤其有用。

所有的单例类至少拥有以下三种公共元素:

它们必须拥有一个构造函数,并且必须被标记为private。
它们拥有一个保存类的实例的静态成员变量。
它们拥有一个访问这个实例的公共的静态方法
和普通类不同的是,单例类不能在其他类中直接实例化。单例类只能被其自身实例化。要获得这样的一种结果, __construct()方法必须被标记为private。如果试图用private构造函数构造一个类,就会得到一个可访问性级别的错误。

要让单例类起作用,就必须使其为其他类提供一个实例,用它调用各种方法。单例类不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。结果 是单例类不会重复占用内存和系统资源,从而让应用程序的其它部分更好地使用这些资源。作为这一模式的一部分,必须创建一个空的私有__clone()方 法,以防止对象被复制或克隆。

返回实例引用的这个方法通常被命名为getTnstance()。这个方法必须是静态的,而且如果它还没有实例化,就必须进行实例化。getInstance() 方法通过使用 instanceof 操作符和self 关键字,可以检测到类是否已经被实例化。

/* 例子:数据库连接职责的集中控制 */
class Database {

    private $_db;
    static $_instance;

//私有的构造函数
    private function __construct() {
        $this->_db = pg_connect('dbname=example_db');
    } 
//防止对象被复制或是克隆
    private __clone() {};

//静态方法
    public static function getInstance() {
        if( ! (self::$_instance instanceof self) ) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function query($sql) {
        // 使用 $this->_db 执行一个查询
        return pg_query($this->_db, $sql);
    }
}

这个例子一开始声明了两个变量:一个实例变量 $_db, 构造对象时这个变量的值会被填充;另一个变量是静态变量,这个变量会保存类仅有的一个实例。

接着是私有的 __construct() 和 __clone() 魔术方法。私有构造函数可以防止外部代码使用 new 操作符来创建对象。类似的。私有的 __clone() 方法消除了php语言中可以复制对象从而破坏单一职责的一个漏洞。

这之后的代码声明了 getInstance() 静态方法,这事单例模式的实际构造。这个方法最后返回实例的引用。

现在,你已经看到了如何声明单例类。但是应该如何使用他呢?例子如下:

$db = Database::getInstance();
$db->query(‘SELECT * FROM example_table ‘);
通过调用 getInstance() 方法,$db 现在存有内部存储实例的引用。通过这个实例,你可以调用单例类中定义的任何非静态方法。

如果这个类不需要使用 __construct() 方法,那么这个类就不大适合使用单例模式。在这种情况下,应该使用纯静态类。你只需要提供一个没有函数体的私有构造函数,并且去掉 getInstance() 和 $_instance 成员就可以做到这一点。这会防止类被实例化。它通过消除使用这段代码时获得实例的可能性确保了单一职责性。例子

class SomeClass {
    //防止类被当作实例使用
    private function __construct() {}
    public static function SomeMethod() {
        //执行一些操作
    }
}

开源队列HTTPSQS的使用

没有评论

2011 年 08 月 29 日 at 下午 2:44分类:PHP

详细内容请见:
http://blog.s135.com/httpsqs/  查看

httpsqs安装好之后还要安装php的httpsqs的拓展
拓展下载地址:下载
安装方法:
mkdir php_httpsqs_client
cd php_httpsqs_client
tar zxvf php_httpsqs_client_0.2.1.tar.gz
/usr/local/php/bin/phpize
./configure –enable-httpsqs –with-php-config=/usr/local/php/bin/php-config
make && make install
#接着在php.ini中添加一行
extension=httpsqs.so;

PHP客户端的使用方法:
上面链接中讲述的有点问题
我们在使用并不需要加载那个客户端的php文件(httpsqs_client.php),
这个文件不要加载的原因是什么,现在我也不是很清楚。估计是项目编译的时候已经生成了一个类 的文件了
所以你在自己定义一个类的话,系统说不能再次定义该类。所以不要加载这个类。

按照上述的在Linux环境下进行编译安装之后,设定数据目录(httpsqs -d -x /var/queue)
记住:这里对好不要使用-a来设置验证密码,因为在代码中并没有任何参数来给你输入这个验证密码,因此出来的结果都是
告诉你,你的验证密码错误。
我们只需要按着这个页面(http://phprimer.com/viewtopic.php?f=3&t=1089)的方法使用就可以了

eg:

<?php
//include_once("httpsqs_client.php"); 

$httpsqs = new HttpSQS('127.0.0.1', '1218');

$str = '1、添加虚拟主机,执行如下命令';

$result = $httpsqs->put('test', urlencode($str) , 'UTF-8');  

$result = $httpsqs->get('test', true, 'UTF-8');

/*
==============================================================

$hr = httpsqs_connect("127.0.0.1", 1218);

$putRes = httpsqs_put($hr, "fbbin", "This is a test Data", "UTF-8");

$content = httpsqs_get($hr, "fbbin", true, "UTF-8");

*/

//$status = httpsqs_status($hr, "fbbin", true);

print_r($result);

?>

jQuery插件实现拖动排序功能

没有评论

2011 年 08 月 25 日 at 上午 11:20分类:jQuery

// jQuery List DragSort v0.4
// Website: http://dragsort.codeplex.com/
// License: http://dragsort.codeplex.com/license

(function($) {

	$.fn.dragsort = function(options) {
		var opts = $.extend({}, $.fn.dragsort.defaults, options);
		var lists = [];
		var list = null, lastPos = null;
		if (this.selector)
			$("head").append("<style type='text/css'>" + (this.selector.split(",").join(" " + opts.dragSelector + ",") + " " + opts.dragSelector) + " { cursor: pointer; }</style>");

		this.each(function(i, cont) {

			if ($(cont).is("table") && $(cont).children().size() == 1 && $(cont).children().is("tbody"))
				cont = $(cont).children().get(0);

			var newList = {
				draggedItem: null,
				placeHolderItem: null,
				pos: null,
				offset: null,
				offsetLimit: null,
				scroll: null,
				container: cont,

				init: function() {
					$(this.container).attr("data-listIdx", i).mousedown(this.grabItem).find(opts.dragSelector).css("cursor", "pointer");
					$(this.container).children(opts.itemSelector).each(function(j) { $(this).attr("data-itemIdx", j);});
				},

				grabItem: function(e) {
					if (e.which != 1 || $(e.target).is(opts.dragSelectorExclude))
						return;

					var elm = e.target;
					while (!$(elm).is("[data-listIdx='" + $(this).attr("data-listIdx") + "'] " + opts.dragSelector)) {
						if (elm == this) return;
						elm = elm.parentNode;
					}

					if (list != null && list.draggedItem != null)
						list.dropItem();

					$(e.target).css("cursor", "move");

					list = lists[$(this).attr("data-listIdx")];
					list.draggedItem = $(elm).closest(opts.itemSelector);
					var mt = parseInt(list.draggedItem.css("marginTop"));
					var ml = parseInt(list.draggedItem.css("marginLeft"));
					list.offset = list.draggedItem.offset();
					list.offset.top = e.pageY - list.offset.top + (isNaN(mt) ? 0 : mt) - 1;
					list.offset.left = e.pageX - list.offset.left + (isNaN(ml) ? 0 : ml) - 1;

					if (!opts.dragBetween) {
						var containerHeight = $(list.container).outerHeight() == 0 ? Math.max(1, Math.round(0.5 + $(list.container).children(opts.itemSelector).size() * list.draggedItem.outerWidth() / $(list.container).outerWidth())) * list.draggedItem.outerHeight() : $(list.container).outerHeight();
						list.offsetLimit = $(list.container).offset();
						list.offsetLimit.right = list.offsetLimit.left + $(list.container).outerWidth() - list.draggedItem.outerWidth();
						list.offsetLimit.bottom = list.offsetLimit.top + containerHeight - list.draggedItem.outerHeight();
					}

					var h = list.draggedItem.height();
					var w = list.draggedItem.width();
					var orig = list.draggedItem.attr("style");
					list.draggedItem.attr("data-origStyle", orig ? orig : "");
					if (opts.itemSelector == "tr") {
						list.draggedItem.children().each(function() { $(this).width($(this).width()); });
						list.placeHolderItem = list.draggedItem.clone().attr("data-placeHolder", true);
						list.draggedItem.after(list.placeHolderItem);
						list.placeHolderItem.children().each(function() { $(this).css({ borderWidth:0, width: $(this).width() + 1, height: $(this).height() + 1 }).html("&nbsp;"); });
					} else {
						list.draggedItem.after(opts.placeHolderTemplate);
						list.placeHolderItem = list.draggedItem.next().css({ height: h, width: w }).attr("data-placeHolder", true);
					}
					list.draggedItem.css({ position: "absolute", opacity: 0.8, "z-index": 999, height: h, width: w });

					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });

					list.scroll = { moveX: 0, moveY: 0, maxX: $(document).width() - $(window).width(), maxY: $(document).height() - $(window).height() };
					list.scroll.scrollY = window.setInterval(function() {
						if (opts.scrollContainer != window) {
							$(opts.scrollContainer).scrollTop($(opts.scrollContainer).scrollTop() + list.scroll.moveY);
							return;
						}
						var t = $(opts.scrollContainer).scrollTop();
						if (list.scroll.moveY > 0 && t < list.scroll.maxY || list.scroll.moveY < 0 && t > 0) {
							$(opts.scrollContainer).scrollTop(t + list.scroll.moveY);
							list.draggedItem.css("top", list.draggedItem.offset().top + list.scroll.moveY + 1);
						}
					}, 10);
					list.scroll.scrollX = window.setInterval(function() {
						if (opts.scrollContainer != window) {
							$(opts.scrollContainer).scrollLeft($(opts.scrollContainer).scrollLeft() + list.scroll.moveX);
							return;
						}
						var l = $(opts.scrollContainer).scrollLeft();
						if (list.scroll.moveX > 0 && l < list.scroll.maxX || list.scroll.moveX < 0 && l > 0) {
							$(opts.scrollContainer).scrollLeft(l + list.scroll.moveX);
							list.draggedItem.css("left", list.draggedItem.offset().left + list.scroll.moveX + 1);
						}
					}, 10);

					list.setPos(e.pageX, e.pageY);
					$(document).bind("selectstart", list.stopBubble); //stop ie text selection
					$(document).bind("mousemove", list.swapItems);
					$(document).bind("mouseup", list.dropItem);
					if (opts.scrollContainer != window)
						$(window).bind("DOMMouseScroll mousewheel", list.wheel);
					return false; //stop moz text selection
				},

				setPos: function(x, y) {
					var top = y - this.offset.top;
					var left = x - this.offset.left;

					if (!opts.dragBetween) {
						top = Math.min(this.offsetLimit.bottom, Math.max(top, this.offsetLimit.top));
						left = Math.min(this.offsetLimit.right, Math.max(left, this.offsetLimit.left));
					}

					this.draggedItem.parents().each(function() {
						if ($(this).css("position") != "static" && (!$.browser.mozilla || $(this).css("display") != "table")) {
							var offset = $(this).offset();
							top -= offset.top;
							left -= offset.left;
							return false;
						}
					});

					if (opts.scrollContainer == window) {
						y -= $(window).scrollTop();
						x -= $(window).scrollLeft();
						y = Math.max(0, y - $(window).height() + 5) + Math.min(0, y - 5);
						x = Math.max(0, x - $(window).width() + 5) + Math.min(0, x - 5);
					} else {
						var cont = $(opts.scrollContainer);
						var offset = cont.offset();
						y = Math.max(0, y - cont.height() - offset.top) + Math.min(0, y - offset.top);
						x = Math.max(0, x - cont.width() - offset.left) + Math.min(0, x - offset.left);
					}
					
					list.scroll.moveX = x == 0 ? 0 : x * opts.scrollSpeed / Math.abs(x);
					list.scroll.moveY = y == 0 ? 0 : y * opts.scrollSpeed / Math.abs(y);

					this.draggedItem.css({ top: top, left: left });
				},
				
				wheel: function(e) {
					if (($.browser.safari || $.browser.mozilla) && list && opts.scrollContainer != window) {
						var cont = $(opts.scrollContainer);
						var offset = cont.offset();
						if (e.pageX > offset.left && e.pageX < offset.left + cont.width() && e.pageY > offset.top && e.pageY < offset.top + cont.height()) {
							var delta = e.detail ? e.detail * 5 : e.wheelDelta / -2;
							cont.scrollTop(cont.scrollTop() + delta);
							e.preventDefault();
						}
					}
				},

				buildPositionTable: function() {
					var item = this.draggedItem == null ? null : this.draggedItem.get(0);
					var pos = [];
					$(this.container).children(opts.itemSelector).each(function(i, elm) {
						if (elm != item) {
							var loc = $(elm).offset();
							loc.right = loc.left + $(elm).width();
							loc.bottom = loc.top + $(elm).height();
							loc.elm = elm;
							pos.push(loc);
						}
					});
					this.pos = pos;
				},

				dropItem: function() {
					if (list.draggedItem == null)
						return;

					$(list.container).find(opts.dragSelector).css("cursor", "pointer");
					list.placeHolderItem.before(list.draggedItem);

					list.draggedItem.attr("style", list.draggedItem.attr("data-origStyle")).removeAttr("data-origStyle");
					list.placeHolderItem.remove();

					$("[data-dropTarget]").remove();

					window.clearInterval(list.scroll.scrollY);
					window.clearInterval(list.scroll.scrollX);

					var changed = false;
					$(lists).each(function() {
						$(this.container).children(opts.itemSelector).each(function(j) {
							if (parseInt($(this).attr("data-itemIdx")) != j) {
								changed = true;
								$(this).attr("data-itemIdx", j);
							}
						});
					});
					if (changed)
						opts.dragEnd.apply(list.draggedItem);
					list.draggedItem = null;
					$(document).unbind("selectstart", list.stopBubble);
					$(document).unbind("mousemove", list.swapItems);
					$(document).unbind("mouseup", list.dropItem);
					if (opts.scrollContainer != window)
						$(window).unbind("DOMMouseScroll mousewheel", list.wheel);
					return false;
				},

				stopBubble: function() { return false; },

				swapItems: function(e) {
					if (list.draggedItem == null)
						return false;

					list.setPos(e.pageX, e.pageY);

					var ei = list.findPos(e.pageX, e.pageY);
					var nlist = list;
					for (var i = 0; ei == -1 && opts.dragBetween && i < lists.length; i++) {
						ei = lists[i].findPos(e.pageX, e.pageY);
						nlist = lists[i];
					}

					if (ei == -1 || $(nlist.pos[ei].elm).attr("data-placeHolder"))
						return false;

					if (lastPos == null || lastPos.top > list.draggedItem.offset().top || lastPos.left > list.draggedItem.offset().left)
						$(nlist.pos[ei].elm).before(list.placeHolderItem);
					else
						$(nlist.pos[ei].elm).after(list.placeHolderItem);

					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
					lastPos = list.draggedItem.offset();
					return false;
				},

				findPos: function(x, y) {
					for (var i = 0; i < this.pos.length; i++) {
						if (this.pos[i].left < x && this.pos[i].right > x && this.pos[i].top < y && this.pos[i].bottom > y)
							return i;
					}
					return -1;
				},

				createDropTargets: function() {
					if (!opts.dragBetween)
						return;
					$(lists).each(function() {
						var ph = $(this.container).find("[data-placeHolder]");
						var dt = $(this.container).find("[data-dropTarget]");
						if (ph.size() > 0 && dt.size() > 0)
							dt.remove();
						else if (ph.size() == 0 && dt.size() == 0)
							$(this.container).append(list.placeHolderItem.clone().removeAttr("data-placeHolder").attr("data-dropTarget", true));
					});
				}
			};
			newList.init();
			lists.push(newList);
		});

		return this;
	};

	$.fn.dragsort.defaults = {
		itemSelector: "li",
		dragSelector: "li",
		dragSelectorExclude: "input, textarea, a[href]",
		dragEnd: function() { },
		dragBetween: false,
		placeHolderTemplate: "<li>&nbsp;</li>",
		scrollContainer: window,
		scrollSpeed: 5
	};

})(jQuery);

使用方法:

使用方法:

$('div ul').dragsort();

对于动态加载的对象,应在激活对象后再使用

//鼠标移动到对象上,触发
$('div li').live('mousedown',function(){
  $('div ul').dragsort();
});

详细:http://www.cnblogs.com/aha/archive/2010/11/27/1889775.html

JS在文本域鼠标指定位置插入文本

没有评论

2011 年 08 月 17 日 at 下午 5:01分类:PHP

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JS在文本域鼠标指定位置插入文本</title>
<script type="text/javascript">
function insertAtCursor(myField, myValue) {
     //IE support
     if (document.selection) {
         myField.focus();
         sel = document.selection.createRange();
         sel.text = myValue;
         sel.select();
     }
     //MOZILLA/NETSCAPE support
     else if (myField.selectionStart || myField.selectionStart == '0') {
         var startPos = myField.selectionStart;
         var endPos = myField.selectionEnd;
         // save scrollTop before insert
         var restoreTop = myField.scrollTop;
         myField.value = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length);
         if (restoreTop > 0) {
         myField.scrollTop = restoreTop;
         }
         myField.focus();
         myField.selectionStart = startPos + myValue.length;
         myField.selectionEnd = startPos + myValue.length;
     } else {
         myField.value += myValue;
         myField.focus();
     }
}
</script>
</head>
<body>
<textarea id="demo" style="width:640px; height:480px">

</textarea>
<input type="button" onclick="insertAtCursor(document.getElementById('demo'),'abc123')" value="insert" />
</body>
</html>