6.1.1 用定义函数的方式定义类
在面向对象的思想中,最核心的概念之一就是类。一个类表示了具有相似性质的一类事物的抽象,通过实例化一个类,可以获得属于该类的一个实例,即对象。
在JavaScript中定义一个类的方法如下:
function class1(){
//类成员的定义及构造函数
}
这里class1既是一个函数也是一个类。可以将它理解为类的构造函数,负责初始化工作。
6.1.2 使用new操作符获得一个类的实例
在前面介绍基本对象时,已经用过new操作符,例如:
new Date();
表示创建一个日期对象,而Date就是表示日期的类,只是这个类是由JavaScript内部提供的,而不是由用户定义的。
new操作符不仅对内部类有效,对用户定义的类也同样有效,对于上节定义的class1,也可以用new来获取一个实例:
function class1(){
//类成员的定义及构造函数
}
var obj1=new class1();
抛
开类的概念,从代码的形式上来看,class1就是一个函数,那么是不是所有的函数都可以用new来操作呢?是的,在JavaScript中,函数和类就
是一个概念,当对一个函数进行new操作时,就会返回一个对象。如果这个函数中没有初始化类成员,那就会返回一个空的对象。例如:
//定义一个hello函数
function hello(){
alert("hello");
}
//通过new一个函数获得一个对象
var obj=new hello();
alert(typeof(obj));
从运行结果看,执行了hello函数,同时obj也获得了一个对象的引用。当new一个函数时,这个函数就是所代表类的构造函数,其中的代码被看作为了初始化一个对象。用于表示类的函数也称为构造器。
6.1.3 使用方括号([ ])引用对象的属性和方法
在JavaScript中,每个对象可以看作是多个属性(方法)的集合,引用一个属性(方法)很简单,如:
对象名.属性(方法)名
还可以用方括号的形式来引用:
对象名["属性(方法)名"]
注意,这里的方法名和属性名是一个字符串,不是原先点(? )号后面的标识符,例如:
var arr=new Array();
//为数组添加一个元素
arr["push"]("abc");
//获得数组的长度
var len=arr["length"];
//输出数组的长度
alert(len);
图6.1显示了执行的结果。
由此可见,上面的代码等价于:
var arr=new Array();
//为数组添加一个元素
arr.push("abc");
//获得数组的长度
var len=arr.length;
//输出数组的长度
alert(len);
这种引用属性(方法)的方式和数组类似,体现了JavaScript对象就是一组属性(方法)的集合这个性质。
这种用法适合不确定具体要引用哪个属性(方法)的情况,例如:一个对象用于表示用户资料,用一个字符串表示要使用的那个属性,就可以用这种方式来引用:
<script language="JavaScript" type="text/javascript">
<!--
//定义了一个User类,包括两个成员age和sex,并指定了初始值。
function User(){
this.age=21;
this.sex="male";
}
//创建user对象
var user=new User();
//根据下拉列表框显示用户的信息
function show(slt){
if(slt.selectedIndex!=0){
alert(user[slt.value]);
}
}
//-->
</script>
<!--下拉列表框用于选择用户信息-->
<select onchange="show(this)">
<option>请选择需要查看的信息:</option>
<option value="age">年龄</option>
<option value="sex">性别</option>
</select>
在这段代码中,使用一个下拉列表框让用户选择查看哪个信息,每个选项的value就表示用户对象的属性名称。这时如果不采用方括号的形式,可使用如下代码来实现:
function show(slt){
if(slt.selectedIndex!=0){
if(slt.value=="age")alert(user.age);
if(slt.value=="sex")alert(user.sex);
}
}
而使用方括号语法,则只需写为:
alert(user[slt.value]);
方括号语法像一种参数语法,可用一个变量来表示引用对象的哪个属性。如果不采用这种方法,又不想用条件判断,可以使用eval函数:
alert(eval("user."+slt.value));
这里利用eval函数的性质,执行了一段动态生成的代码,并返回了结果。
实际上,在前面讲述document的集合对象时,就有类似方括号的用法,比如引用页面中一个名为“theForm”的表单对象,以前的用法是:
document.forms["theForm"];
也可以改写为:
document.forms.theForm;
forms对象是一个内部对象,和自定义对象不同的是,它还可以用索引来引用其中的一个属性。
6.1.4 动态添加、修改、删除对象的属性和方法
上一节介绍了如何引用一个对象的属性和方法,现在介绍如何为一个对象添加、修改或者删除属性和方法。
其
他语言中,对象一旦生成,就不可更改,要为一个对象添加、修改成员必须要在对应的类中修改,并重新实例化,程序也必须重新编译。JavaScript提供
了灵活的机制来修改对象的行为,可以动态添加、修改、删除属性和方法。例如:先用类Object来创建一个空对象user:
var user=new Object();
1.添加属性
这时user对象没有任何属性和方法,可以为它动态的添加属性,例如:
user.name="jack";
user.age=21;
user.sex="male";
通过上述语句,user对象具有了三个属性:name、age和sex。下面输出这三个语句:
alert(user.name);
alert(user.age);
alert(user.sex);
由代码运行效果可知,三个属性已经完全属于user对象了。
2.添加方法
添加方法的过程和添加属性类似:
user.alert=function(){
alert("my name is:"+this.name);
}
这就为user对象添加了一个方法“alert”,通过执行它,弹出一个对话框显示自己的名字:
user.alert();
图6.2显示了执行的结果。
3.修改属性和方法
修改一个属性和方法的过程就是用新的属性替换旧的属性,例如:
user.name="tom";
user.alert=function(){
alert("hello,"+this.name);
}
这样就修改了user对象name属性的值和alert方法,它从显示“my name is”对话框变为了显示“hello”对话框。
4.删除属性和方法
删除一个属性和方法的过程也很简单,就是将其置为undefined:
user.name=undefined;
user.alert=undefined;
这样就删除了name属性和alert方法。
在添加、修改或者删除属性时,和引用属性相同,也可以采用方括号([])语法:
user["name"]="tom";
使用这种方式还有一个特点,可以使用非标识符字符串作为属性名称,例如标识符中不允许以数字开头或者出现空格,但在方括号([])语法中却可以使用:
user["my name"]="tom";
需要注意,在使用这种非标识符作为名称的属性时,仍然要用方括号语法来引用:
alert(user["my name"]);
而不能写为:
alert(user.my name);
事实上,JavaScript中的每个对象都是动态可变的,这给编程带来了灵活性,也和其他语言产生了区别。
6.1.5 使用大括号({ })语法创建无类型对象
传统的面向对象语言中,每个对象都会对应到一个类。上一节讲this指针时提到,JavaScript中的对象其实就是属性(方法)的一个集合,并没有严格意义上类的概念。所以它提供了一种简单的方式来创建对象,即大括号({})语法:
{
property1:statement,
property2:statement2,
…,
propertyN:statmentN
}
通过大括号括住多个属性或方法及其定义(这些属性或方法用逗号隔开),来实现对象的定义,这段代码就直接定义个了具有n个属性或方法的对象,其中属性名和其定义之间用冒号(:)隔开。例如:
<script language="JavaScript" type="text/javascript">
<!--
var obj={}; //定义了一个空对象
var user={
name:"jack", //定义了name属性,初始化为jack
favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
hello:function(){ //定义了方法hello
alert("hello,"+this.name);
},
sex:"male" //定义了性别属性sex,初始化为male
}
//调用user对象的方法hello
user.hello();
//-->
</script>
第一行定义了一个无类型对象obj,它等价于:
var obj=new Object();
接着定义了一个对象user及其属性和方法。注意,除了最后一个属性(方法)定义,其他的必须以逗号(,)结尾。其实,使用动态增减属性的方法也可以定义一个完全相同的user对象,读者可使用前面介绍的方法实现。
使用这种方式来定义对象,还可以使用字符串作为属性(方法)名,例如:
var obj={"001":"abc"}
这就给对象obj定义了一个属性“001”,这并不是一个有效的标识符,所以要引用这个属性必须使用方括号语法:
obj["001"];
由此可见,无类型对象提供了一种创建对象的简便方式,它以紧凑和清晰的语法将一个对象体现为一个完整的实体。而且也有利于减少代码的体积,这对JavaScript代码来说尤其重要,减少体积意味着提高了访问速度。
6.1.6 prototype原型对象
prototype
对象是实现面向对象的一个重要机制。每个函数(function)其实也是一个对象,它们对应的类是“Function”,但它们身份特殊,每个函数对象
都具有一个子对象prototype。即prototype表示了该函数的原型,而函数也是类,prototype就是表示了一个类的成员的集合。当通过
new来获取一个类的对象时,prototype对象的成员都会成为实例化对象的成员。
既然prototype是一个对象,可以使用前面两节介绍的方法对其进行动态的修改,这里先给出一个简单的例子:
//定义了一个空类
function class1(){
//empty
}
//对类的prototype对象进行修改,增加方法method
class1.prototype.method=function(){
alert("it's a test method");
}
//创建类class1的实例
var obj1=new class1();
//调用obj1的方法method
obj1.method();
图6.3显示了执行的结果。
linux下安装BugZilla
Bugzilla安装需要perl5.6.1及以上版本、mysql4.0.14及以上版本(PostgreSQL7.3.x及以上版本)
1、下载bugzilla
从 http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-2.20.4.tar.gz 下载bugzilla。
(据说版本号中间的数字为偶数代表稳定版,为奇数代表测试版)
2、下载bugzilla中文包
从 http://nchc.dl.sourceforge.net/sourceforge/bugzilla-cn/bugzilla-2.20-cn-1.0.zip 下载中文包。
3、解压bugzilla
tar zxvf bugzilla-2.20.4.tar.gz
cd bugzilla-2.20.4
4、运行checksetup检查bugzilla依赖的perl模块是否安装完全。
./checksetup.pl --check-modules
5、安装缺少的perl模块。安装方法:
a)如果缺少安装bugzilla必须的perl模块,执行第4步后会有缺少的perl模块的列表显示。
使用perl -MCPAN -e 'install ""',将缺少的perl模块都安装上去。
b)使用perl -MCPAN -e 'install "Bundle::Bugzilla"'自动安装bugzilla依赖的所有perl模块,
遇到提示输入时直接回车。
6、生成localconfig文件。执行:
./checksetup.pl 生成localconfig文件,修改该文件的数据库用户名密码等信息。
//为BugZilla建立数据库用户和密码,并授权.
GRANT SELECT, INSERT,
UPDATE, DELETE, INDEX, ALTER, CREATE, LOCK TABLES,
CREATE TEMPORARY TABLES, DROP, REFERENCES ON bugs.*
TO bugs@localhost IDENTIFIED BY '$db_pass';
FLUSH PRIVILEGES;
7、生成bugzilla需要的数据库schema。执行:
./checksetup.pl 生成BugZilla所需要的数据库schema.
数据库schema生成完成后,将会提示输入管理员邮件地址、真实用户名、密码。
8、配置apache,修改httpd.conf文件(假设将bugzilla安装在/var/www/html/bugzilla),增加:
AddHandler cgi-script .cgi
Options +Indexes +ExecCGI
DirectoryIndex index.cgi
AllowOverride Limit
9、中文支持
切换到下载bugzilla-2.20-cn-1.0.zip目录。
unzip -d bugzilla-cn bugzilla-2.20-cn-1.0.zip
cd bugzilla-cn
unzip -d cn_UTF8 cn_UTF8.zip
mv cn_UTF8/ /var/www/html/bugzilla/template/cn
然后使用管理员账号登陆bugzilla,在页面底部有个Parameters(系统参数设置)功能,进入后,
修改languages项的值为cn,保存,则以后见到的Bugzilla页面就是汉语页面了。如果想返回英文界面,将 cn 改回 en 即可。
10、修改bugzilla的界面显示:
unzip -d custom custom.zip
cp -fr custom /var/www/html/bugzilla/skins/
注:
1、允许大附件:在/etc/my.cnf中(mysql配置文件)增加:
[mysqld]
# Allow packets up to 1M
max_allowed_packet=1M
2、允许少量词的全文检索,在/etc/my.cnf文件中增加:
[mysqld]
# Allow small words in full-text indexes
ft_min_word_len=2
默认情况下,必须要有至少4个字符才能进行全文检索。
3、允许bugzilla数据库中的attachments表大小能超过4GB.
mysql> use $bugs_db //$bugs_db为bugzilla使用的数据库。
mysql> ALTER TABLE attachments
AVG_ROW_LENGTH=1000000, MAX_ROWS=20000;
上面命令将attachments表大小增加到20GB。
4、中文支持和修改bugzilla的界面显示在bugzilla-cn bugzilla-2.20-cn-1.0.zip包中有详细说明。
汉化要注意版本的匹配。
5、bugzill参数设置及其他相关设置参考官方文档:
http://www.bugzilla.org/docs/
转自: http://wiflish.javaeye.com/blog/53414
Node往往被翻译为节点,在一个对象(可以简单的理解为是HTML页面中),一个属性
name="aaa"可以是一个节点,一个
< div id="aaa">……< /div>也可以是一个节点,在
< body>……< /body>中的,也是一个大大的节点。下面是一些有关Node的属性和方法,并没有包含部分不兼容IE和FF内容的讲解。
Node的属性介绍:
nodeType:显示节点的类型
nodeName:显示节点的名称
nodeValue:显示节点的值
attributes:获取一个属性节点
firstChild:表示某一节点的第一个节点
lastChild:表示某一节点的最后一个子节点
childNodes:表示所在节点的所有子节点
parentNode:表示所在节点的父节点
nextSibling:紧挨着当前节点的下一个节点
previousSibling:紧挨着当前节点的上一个节点
ownerDocument:(不知)
Node有各种各样的节点,我们先花一些时间认识他们,同时一并了解nodeType,nodeName和nodeValue属性:
名称:元素节点
nodeType:ELEMENT_NODE
nodeType值:1
nodeName:元素标记名
nodeValue:null
<body>
<div id = "t" ><span></span></div>
</body>
<script>
var d = document.getElementById("t");
document.write(d.nodeType);
document.write(d.nodeName);
document.write(d.nodeValue);
//显示 1 DIV null
</script>
名称:属性节点
nodeType:ATTRIBUTE_NODE
nodeType值:2
nodeName:属性名
nodeValue:属性值
<body>
<div id = "t" name="aaa"><span></span></div>
</body>
<script>
var d = document.getElementById("t").getAttributeNode("name");
document.write(d.nodeType);
document.write(d.nodeName);
document.write(d.nodeValue);
//显示 2 name aaa
</script>
名称:文本节点
nodeType:TEXT_NODE
nodeType值:3
nodeName:#text
nodeValue:文本内容
<body>
<div id = "t">bbb</div>
</body>
<script>
var d = document.getElementById("t").firstChild;
document.write(d.nodeType);
document.write(d.nodeName);
document.write(d.nodeValue);
//显示 3 #text bbb
</script>
名称:CDATA文本节点(XML中传递文本的格式)
nodeType:CDATA_SECTION_NODE
nodeType值:4
nodeName:#cdata-section
nodeValue:CDATA文本内容
(作者省略8个属性,需技术补充)
attributes属性,直接获取一个属性节点,注意这里要使用[],保持IE和FF的兼容性。
<body name="ddd">
<div id = "t" name = "aaa"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t").attributes["name"];
document.write(d.name);
document.write(d.value);
//显示 name aaa
</script>
firstChild和lastChild属性,表示某一节点的第一个和最后一个子节点:
<body>
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t");
document.write(d.firstChild.innerHTML);
document.write(d.lastChild.innerHTML);
//显示 aaa ccc
</script>
childNodes和parentNode属性,表示所在节点的所有子节点和所在节点的父节点,这里的childNodes注意是一个数组:
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t");
document.write(d.childNodes[1].innerHTML);
document.write(d.parentNode.getAttribute("name"));
//显示 bbb ddd
</script>
nextSibling和previousSibling属性,分别表示在parentNode的childNodes[]数组中,紧挨着当前节点的上一个和下一个节点:
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t").childNodes[1];
document.write(d.nextSibling.innerHTML);
document.write(d.previousSibling.innerHTML);
//显示 ccc aaa
</script>
ownerDocument属性(不知如何使用)
Node的方法介绍:
hasChildNodes():判定一个节点是否有子节点
removeChild():去除一个节点
appendChild():添加一个节点
replaceChild():替换一个节点
insertBefore():指定节点位置插入一个节点
cloneNode():复制一个节点
normalize():(不知)
hasChildNodes()方法:判定一个节点是否有子节点,有返回true,没有返回false
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
<div id = "m"></div>
</body>
<script>
alert(document.getElementById("t").hasChildNodes());
alert(document.getElementById("m").hasChildNodes());
// 第一个true,第二个false
</script>
removeChild()方法:去除一个节点
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t").firstChild;
document.getElementById("t").removeChild(d);
// <span>aaa</span>被去除
</script>
appendChild()方法:添加一个节点,如果文档树中已经存在该节点,则将它删除,然后在新位置插入。
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var d = document.getElementById("t").firstChild;
document.getElementById("t").appendChild(d);
// <span>aaa</span>成了最后一个节点
</script>
replaceChild()方法:从文档树中删除(并返回)指定的子节点,用另一个节点来替换它。
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var newd = document.createElement("span");
newd.innerHTML = "eee";
var oldd = document.getElementById("t").lastChild;
document.getElementById("t").replaceChild(newd,oldd);
// 最后一项成了 eee
</script>
insertBefore()方法:在指定节点的前面插入一个节点,如果已经存在,则删除原来的,然后在新位置插入
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div>
</body>
<script>
var newd = document.createElement("span");
newd.innerHTML = "eee";
var where = document.getElementById("t").lastChild;
document.getElementById("t").insertBefore(newd,where);
// 在最后一项的前面多了一项 eee
</script>
cloneNode()方法:复制一个节点,该方法有一个参数,true表示同时复制所有的子节点,false表示近复制当前节点
<body name="ddd">
<div id = "t"><span>aaa</span><span>bbb</span><span>ccc</span></div><div id = "m"></div>
</body>
<script>
var what = document.getElementById("t").cloneNode(false).innerHTML;
document.getElementById("m").innerHTML = what;
// 增加了一个aaabbbccc
</script>
文章来自: JavaScript Sky
Beta,这个希腊字母的英文写法,怎么会变成了“测试”的含义。据我所知的,广义上对测试有三个传统的称呼,alpha、beta、gamma,用来标
识测试的阶段和范围。alpha 是指内测,即现在说的 CB,指开发团队内部测试的版本或者有限用户体验测试版本。beta
是指公测,即针对所有用户公开的测试版本。然后做过一些修改,成为正式发布的候选版本时(现在叫做 RC - Release
Candidate),叫做 gamma。
作者以轻松的语言比喻了java的23种模式,有很好的启发作用。
创建型模式
1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory
工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
2、BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语
言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞掂,这就是我的“我爱你”
builder。(这一定比美军在伊拉克用的翻译机好卖)
建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
3、FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory
Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
4、PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)
原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减
少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
5、SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
结构型模式
6、ADAPTER—在朋友聚会上碰到了一个美女Sarah,从香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)
适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
7、BRIDGE—早上碰到MM,要说早上好,晚上碰到MM,要说晚上好;碰到MM穿了件新衣服,要说你的衣服好漂亮哦,碰到MM新做的发型,要说你的头
发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题,自己用BRIDGE组合一下不就行了
桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
8、COMPOSITE—Mary今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件T恤挺漂亮,买,这条裙子好看,
买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”
“……”,MM都会用Composite模式了,你会了没有?
合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。
9、DECORATOR—Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写
上“最好的的礼物,就是爱你的Fita”,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起
来……,我们都是Decorator,最终都在修饰我这个人呀,怎么样,看懂了吗?
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
10、FACADE—我有一个专业的Nikon相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相
机有Facade设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样MM也可以用这个相机给我拍张照片了。
门面模式:外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。
11、FLYWEIGHT—每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上
MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴
状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享
的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被
共享的对象。享元模式大幅度的降低内存中对象的数量。
12、PROXY—跟MM在网上聊天,一开头总是“hi,你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?”这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自动的回答,接收到其他的话时再通知我回答,怎么样,酷吧。
代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情
况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以
并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。
行为模式
13、CHAIN OF
RESPONSIBLEITY—晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi,可以做我的女朋友
吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的MM把纸条传给老师了,听说是个老处女呀,快跑!
责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接
起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情
况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。
14、COMMAND—俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。
这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,
才请我吃面。”,:-(
命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和
发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统
支持命令的撤消。
15、INTERPRETER—俺有一个《泡MM真经》,上面有各种泡MM的攻略,比如说去吃西餐的步骤、去看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了。
解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模
式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要
定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任
何排列组合都是一个语言。
16、ITERATOR—我爱上了Mary,不顾一切的向她求婚。
Mary:“想要我跟你结婚,得答应我的条件”
我:“什么条件我都答应,你说吧”
Mary:“我看上了那个一克拉的钻石”
我:“我买,我买,还有吗?”
Mary:“我看上了湖边的那栋别墅”
我:“我买,我买,还有吗?”
Mary:“你的小弟弟必须要有50cm长”
我脑袋嗡的一声,坐在椅子上,一咬牙:“我剪,我剪,还有吗?”
……
迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容
器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代
子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
17、MEDIATOR—四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话。
调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会
立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协
作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
18、MEMENTO—同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。
备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
19、OBSERVER—想知道咱们公司最新MM情报吗?加入公司的MM情报邮件组就行了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦
观察者模式:观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
20、STATE—跟MM交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的MM就会说“有事情
啦”,对你不讨厌但还没喜欢上的MM就会说“好啊,不过可以带上我同事么?”,已经喜欢上你的MM就会说“几点钟?看完电影再去泡吧怎么样?”,当然你看
电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。
状态模式:状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对
象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统
可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
21、STRATEGY—跟不同类型的MM约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到MM的芳心,我的追MM锦囊中有好多Strategy哦。
策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况
下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影
响到环境和客户端。
22、TEMPLATE
METHOD——看过《如何说服女生上床》这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八
大步骤(Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦(具体实现);
模板方法模式:模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类
可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
23、VISITOR—情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一
个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻
松多了;
访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式
适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很
容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对
象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
(来源:blog.csdn.net,http://www.jdon.com)