网络上分享的一些资源:
用South重命名数据表名
执行以下命令:
|
|
再生成的文件里面修改代码:
|
|
使用Virtualenv搭建独立的Python环境
安装Virtualenv
Virtualenv实际上是一个python包,所以我们可以用easy_install或者pip安装。
|
|
创建python虚拟环境
使用virtualenv命令创建python虚拟环境:virtualenv [env1]
|
|
执行后,在本地会生成一个与虚拟环境同名的文件夹。
如果想依赖系统环境的第三方软件包,可以使用参数–system-site-packages:
|
|
启动虚拟环境
进入虚拟环境目录,启动虚拟环境,
|
|
此时命令行前面会多出一个括号,括号里为虚拟环境的名称。以后easy_install或者pip安装的所有模块都会安装到该虚拟环境目录里。
退出虚拟环境
执行命令:deactivate
|
|
使用virtualenvwrapper
virtualenvwrapper是virtualenv的扩展工具,可以方便的创建、删除、复制、切换不同的虚拟环境。
安装virtualenvwrapper
|
|
创建一个文件夹,用于存放所有的虚拟环境:
|
|
将下面代码添加到~/.bashrc
里
|
|
执行:source ~/.bashrc
使用virtualenvwrapper
1.创建虚拟环境:mkvirtualenv [env1]
|
|
mkvirtualenv可以使用virtualenv的参数,比如–python来指定python版本。创建虚拟环境后,会自动切换到此虚拟环境里。虚拟环境目录都在WORKON_HOME里。
2.列出虚拟环境:lsvirtualenv -b
|
|
3.切换虚拟环境:workon [env1]
|
|
4.查看环境里安装了哪些包:lssitepackages
5.进入当前环境的目录:cdvirtualenv [子目录名]
|
|
进入当前环境的site-packages目录:cdsitepackages [子目录名]
|
|
6.控制环境是否使用global site-packages:toggleglobalsitepackages
7.复制虚拟环境:cpvirtualenv [source] [dest]
|
|
8.退出虚拟环境:deactivate
9.删除虚拟环境:rmvirtualenv [虚拟环境名称]
|
|
将Sublime打造成Markdown编辑器
安装Package Control
打开Sublime Text,按下组合键 Ctrl+` ,出现控制台,输入:
|
|
安装Markdown Preview
按下Ctrl+Shift+p
调出命令面板,找到Package Control: Install Pakage
这一项。搜索 markdown preview,点击安装。
使用
Markdown Preview常用的功能是preview in browser
和Export HTML in Sublime Text
,前者可以在浏览器中看到效果,后者可将markdown保持为html文件。
快捷键
在Preferences -> Key Bindings User
打开的文件中添加以下代码:
|
|
设置语法高亮和mathjax支持
在Preferences -> Package Settings -> Markdown Preview -> Setting User
中,将下面设置项改为true即可
|
|
安装Smart Markdown
按下Ctrl+Shift+p
调出命令面板,找到Package Control: Install Pakage
这一项。搜索 smart markdown,点击安装。
在Github上搭建Jekyll博客
创建库
在Github中创建一个名为username.github.io
的库
安装Jekyll
|
|
目录结构图
|
|
配置文件
_config.yml
里面设置站点主要配置信息
|
|
域名配置
CNAME
这个文件写明了这个站点的域名,如果不喜欢username.github.io
的话,可以改掉
博客存放
_posts
下的所有目录中的所有博客,都会被Jekyll处理成为静态的html文件,然后放在_site
下。
所以要把以下目录添加到.gitignore
文件。
|
|
在_posts
下的符合YYYY-MM-DD-xxxxxx.md
的文件,都会被Jekyll认定为博客内容。我在_posts
下又新建了一些文件夹,主要是方便自己本地管理博客。
在上述这些文件中,必须先定义一些配置项,例如这篇博客的md文件中,开头是这样的:
|
|
除了自定义常量外的必须包含进去,自定义变量在这个布局中可以访问。
模版文件
剩余的目录,基本都属于模板文件了,我解释一下各自的作用:
_includes
可以在模板中随时包含的文件_layouts
布局文件,在博客头配置中可以选择pages
站内固定的页面public
公共资源,包括js
,css
,img
等,还有我博客中调用的图片,我都放这里index.html
站点的首页,整个站的入口文件sitemap.txt
给搜索引擎看的,如何爬取这个站
本地预览及提交
本地预览自己的修改很容易,只要进入username.github.io
目录,执行
|
|
然后访问http://localhost:4000
就OK了,如果想脱离终端在后台运行,加参数--detach
|
|
自己预览过没有问题以后,就提交到服务端吧,Git三步走
|
|
参考
设计模式详解及PHP实现
由于工作中需要写一个比较复杂的类库,这个类库需要很高的扩展性、维护性及复用性。为了麻烦现在简单未来,使用设计模式思想来优化类库可以使工作事半功倍,在这里记录一下各种设计模式,总结一下知识,顺便也可以做为自己日后的参考。
设计模式(Design Patterns)
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 –百度百科
In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. –Wikipedia
在软件开发过程中,一个功能的实现方式多种多样,不同方法的可扩展性、可维护性以及复用性都是不一样的。随着一个人对自己项目代码的要求增加,他会逐渐思考和实践出自己的一套方法或者思想,这种方法或思想决定了他设计出的架构或者编写出的代码的质量优劣。设计模式就属于这样一种经验的积累,是由大量优秀的工程师或者架构师总结和提炼的精华,学习好设计模式等于让我们站在了巨人的肩膀上,从一个高的起点出发,可以避免走很多弯路。
设计模式的使用一定是根据场景来选择的,而且设计模式的实现方式也不是固定的,我们一定要在理解现有设计模式的基础上,根据自己实际的情况不断实践不断理解。就像所谓的《泡妞大全》,读千万遍都不如实践一次来的实际。
如果你对设计模式完全没有感觉,那么去好好写一个类库,或者一个简单的MVC框架,这个过程会让你感觉到自己缺失的部分。
分类
在《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software) 这本书中,作者把设计模式分了三大类:
创建型模式(Creational patterns)
创建型模式是为了解决创建对象时候遇到的问题。因为基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式有两个主导思想:一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合方式。
最常见的五种创建型模式如下:
- 工厂方法模式(Factory method pattern)
- 抽象工厂模式(Abstract factory pattern)
- 单例模式(Singleton pattern)
- 建造者模式(Builder pattern)
- 原型模式(Prototype pattern)
结构型模式(Structural pattern)
结构型模式是通过定义一个简单的方法来实现和了解实体间关系,从而简化设计。
- 适配器模式(Adapter pattern)
- 桥接模式(Bridge pattern)
- 合成模式(Composite pattern)
- 装饰器模式(Decorator pattern)
- 门面模式(Facade pattern)
- 代理模式(Proxy pattern)
- 享元模式(Flyweight Pattern)
行为型模式(Behavioral pattern)
行为型模式用来识别对象之间的常用交流模式并加以实现,使得交流变得更加灵活。
- 策略模式(Strategy pattern)
- 模板方法模式(Template method pattern)
- 观察者模式(Observer pattern)
- 迭代器模式(Iterator pattern)
- 责任链模式(Chain of responsibility pattern)
- 命令模式(Command pattern)
- 备忘录模式(Memento pattern)
- 状态模式(State pattern)
- 访问者模式(Visitor pattern)
- 中介者模式(Mediator pattern)
- 解释器模式(Interpreter pattern)
关系
这里有一张各个模式关系图,可以在了解各个模式以后梳理一下
参考
建造者模式(Builder pattern)
建造者模式是一种创建型模式,它可以让一个产品的内部表象和和产品的生产过程分离开,从而可以生成具有不同内部表象的产品。
Builder模式中主要角色
- 抽象建造者(Builder)角色:定义抽象接口,规范产品各个部分的建造,必须包括建造方法和返回方法。
- 具体建造者(Concrete)角色:实现抽象建造者接口。应用程序最终根据此角色中实现的业务逻辑创造产品。
- 导演者(Director)角色:调用具体的建造者角色创造产品。
- 产品(Product)角色:在导演者的指导下所创建的复杂对象。
适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
类图
实例
|
|
优缺点
优点
建造者模式可以很好的将一个对象的实现与相关的“业务”逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易。
缺点
建造者接口的修改会导致所有执行类的修改。
参考
单例模式(Singleton pattern)
抽象工厂模式是一种创建型模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在。
实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。
单例模式中主要角色
Singleton定义一个getInstance操作,允许客户访问它唯一的实例。
这个例子也简单,就像我有6个老婆(快醒醒!),她们在喊”老公”的时候都是指我。不管什么时候,喊老公擦地,做饭,洗衣服都是指同一个人,PHP不编写多线程,所以不存在抢占问题,如果换别的语言编写,一定得考虑到抢占问题!老公是不可以边擦地边做饭的!
适用性
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
- 当这个唯一实例应该是通过子类化可扩展的。并且用户应该无需更改代码就能使用一个扩展的实例时。
类图
实例
|
|
在此实例中,Singleton禁止了克隆及外部初始化,使得此类只可以通过getInstance()
方法来获得实例,而这个实例只会在第一次使用时创建,以后每次都获得同一实例。
优缺点
优点
- 对唯一实例的受控访问
- 缩小命名空间 单例模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染命名空间
- 允许对操作和表示的精华,单例类可以有子类。而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。
- 允许可变数目的实例(多例模式)
- 比类操作更灵活
缺点
单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。
参考
适配器模式(Adapter pattern)
适配器模式是一种结构型模式,它将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类别自己的接口包裹在一个已存在的类中。
适配器模式中主要角色
- 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所期待得到的
- 源(Adaptee)角色:需要进行适配的接口
- 适配器(Adapter)角色:对Adaptee的接口与Target接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类
适用性
1、你想使用一个已经存在的类,而它的接口不符合你的需求
2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口(仅限于对象适配器)
类适配器模式与对象适配器
类适配器:Adapter与Adaptee是继承关系
- 用一个具体的Adapter类和Target进行匹配。结果是当我们想要一个匹配一个类以及所有它的子类时,类Adapter将不能胜任工作
- 使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子集
- 仅仅引入一个对象,并不需要额外的指针以间接取得adaptee
对象适配器:Adapter与Adaptee是委托关系
- 允许一个Adapter与多个Adaptee同时工作。Adapter也可以一次给所有的Adaptee添加功能
- 使用重定义Adaptee的行为比较困难
类图
类适配器
对象适配器
实例
类适配器
|
|
对象适配器
|
|
参考
桥接模式(Bridge pattern)
桥接模式是一种结构型模式,它是软件设计模式中最复杂的模式之一,它把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。事物对象仅是一个抽象的概念。如“圆形”、“三角形”归于抽象的“形状”之下,而“画圆”、“画三角”归于实现行为的“画图”类之下,然后由“形状”调用“画图”。
主要角色
- 抽象化(Abstraction)角色:定义抽象类的接口并保存一个对实现化对象的引用。
- 修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
- 实现化(Implementor)角色:定义实现类的接口,不给出具体的实现。此接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以完全不同。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
- 具体实现化(Concrete Implementor)角色:实现实现化角色接口并定义它的具体实现。
适用性
- 如果一个系统需要在构件的抽象化和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。
- 设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。
- 一个构件有多于一个的抽象化角色和实现化角色,并且系统需要它们之间进行动态的耦合。
- 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
类图
实例
|
|
优点
- 分离接口及其实现部分, 将Abstraction与Implementor分享有助于降低对实现部分编译时刻的依赖性, 接口与实现分享有助于分层,从而产生更好的结构化系统
- 提高可扩充性
- 实现细节对客户透明。
参考
合成模式(Composite pattern)
合成模式是一种结构型模式,它将对象组合成树形结构以表示”部分-整体”的层次结构。Composite使用户对单个对象和组合对象的使用具有一致性。
Composite变化的是一个对象的结构和组成。
主要角色
- 抽象组件(Component)角色:抽象角色,给参加组合的对象规定一个接口。在适当的情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子组件
- 树叶组件(Leaf)角色:在组合中表示叶节点对象,叶节点没有子节点。在组合中定义图元对象的行为。
- 树枝组件(Composite)角色:存储子部件。定义有子部件的那些部件的行为。在Component接口中实现与子部件有关的操作。
- 客户端(Client):通过Component接口操纵组合部件的对象
适用性
- 你想表示对象的部分-整体层次结构。
- 你希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象。
类图
安全式合成模式
透明式合成模式
实例
安全式合成模式
在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的。因为树叶类型的对象根本就没有管理子类的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。编译通不过,就不会出现运行时期错误。这样的缺点是不够透明,因为树叶类和合成类将具有不同的接口。
|
|
透明式合成模式
在Composite类里面声明所有的用来管理子类对象的方法。这样做的是好处是所有的组件类都有相同的接口。在客户端看来,树叶类和合成类对象的区别起码在接口层次上消失了,客户端可以同等的对待所有的对象。这就是透明形式的合成模式,缺点就是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此调用其添加或删除方法就没有意义了,这在编译期间是不会出错的,而只会在运行时期才会出错。
|
|
优缺点
优点
- 简化客户代码
- 使得更容易增加新类型的组件
缺点
- 使你的设计变得更加一般化,容易增加组件也会产生一些问题,那就是很难限制组合中的组件
参考
装饰器模式(Decorator pattern)
装饰器模式是一种结构型模式,它动态的给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活【GOF95】
装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
主要角色
- 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。
- 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。
- 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。
- 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。
适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。
- 当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
类图
实例
|
|
优缺点
优点
- 比静态继承更灵活;
- 避免在层次结构高层的类有太多的特征
缺点
- 使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。
参考
门面模式(Facade pattern)
门面模式是一种结构型模式,它为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层次的接口,使得子系统更加容易使用。
主要角色
门面(Facade)角色
- 此角色将被客户端调用
- 知道哪些子系统负责处理请求
- 将用户的请求指派给适当的子系统
子系统(subsystem)角色
- 实现子系统的功能
- 处理由Facade对象指派的任务
- 没有Facade的相关信息,可以被客户端直接调用
- 可以同时有一个或多个子系统,每个子系统都不是一个单独的类,而一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并知道门面模式的存在,对于子系统而言,门面仅仅是另一个客户端。
适用性
- 为一些复杂的子系统提供一组接口
- 提高子系统的独立性
- 在层次化结构中,可以使用门面模式定义系统的每一层的接口
类图
实例
|
|
优缺点
优点
- 它对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便
- 实现了子系统与客户之间的松耦合关系
- 如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择
参考
享元模式(Flyweight Pattern)
享元模式是一种结构型模式,它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
主要角色
- 抽象享元(Flyweight角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外蕴状态的操作可以通过调用商业以参数形式传入
- 具体享元(ConcreteFlyweight角色:实现Flyweight接口,并为内部状态(如果有的话)拉回存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的
- 不共享的具体享元(UnsharedConcreteFlyweight)角色:并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能,但它并不强制共享。
- 享元工厂(FlyweightFactory)角色:负责创建和管理享元角色。本角色必须保证享元对象可能被系统适当地共享
- 客户端(Client)角色:本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态
适用性
- 一个应用程序使用了大量的对象
- 完全由于使用大量的对象,造成很大的存储开销
- 对象的大多数状态都可变为外部状态
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
- 应用程序不依赖于对象标识。
类图
实例
|
|
优缺点
优点
- Flyweight模式可以大幅度地降低内存中对象的数量。
缺点
- Flyweight模式使得系统更加复杂
- Flyweigth模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长
参考
观察者模式(Observer pattern)
观察者模式是一种行为型模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式
主要角色
- 抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。抽象主题提供了增加和删除观察者对象的接口。
- 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。
- 具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
- 具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。
适用性
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。
- 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。
类图
实例
|
|
优缺点
优点
- 观察者和主题之间的耦合度较小。
- 支持广播通信。
缺点
- 由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。
参考
原型模式(Prototype pattern)
原型模式是一种创建者模式,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。
原型模式中主要角色
- 抽象原型(Prototype)角色:声明一个克隆自己的接口
- 具体原型(Concrete Prototype)角色:实现一个克隆自己的操作
适用性
- 当一个系统应该独立于它的产品创建、构成和表示时,要使用Prototype模式
- 当要实例化的类是在运行时刻指定时,例如动态加载
- 为了避免创建一个与产品类层次平等的工厂类层次时;
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些
类图
实例
|
|
优缺点
优点
- 可以在运行时刻增加和删除产品
- 可以改变值以指定新对象
- 可以改变结构以指定新对象
- 减少子类的构造
- 用类动态配置应用
缺点
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
参考
代理模式(Proxy pattern)
代理模式是一种结构型模式,它可以为其他对象提供一种代理以控制对这个对象的访问。
主要角色
- 抽象主题角色(Subject):它的作用是统一接口。此角色定义了真实主题角色和代理主题角色共用的接口,这样就可以在使用真实主题角色的地方使用代理主题角色。
- 真实主题角色(RealSubject):隐藏在代理角色后面的真实对象。
- 代理主题角色(ProxySubject):它的作用是代理真实主题,在其内部保留了对真实主题角色的引用。它与真实主题角色都继承自抽象主题角色,保持接口的统一。它可以控制对真实主题的存取,并可能负责创建和删除真实对象。代理角色并不是简单的转发,通常在将调用传递给真实对象之前或之后执行某些操作,当然你也可以只是简单的转发。 与适配器模式相比:适配器模式是为了改变对象的接口,而代理模式并不能改变所代理对象的接口。
适用性
- 为一些复杂的子系统提供一组接口
- 提高子系统的独立性
- 在层次化结构中,可以使用门面模式定义系统的每一层的接口
类图
实例
|
|
参考
策略模式(Strategy pattern)
策略模式是一种行为型模式,它定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式可以使算法可独立于使用它的客户而变化。
主要角色
- 抽象策略(Strategy)角色:定义所有支持的算法的公共接口。通常是以一个接口或抽象来实现。Context使用这个接口来调用其ConcreteStrategy定义的算法
- 具体策略(ConcreteStrategy)角色:以Strategy接口实现某具体算法
- 环境(Context)角色:持有一个Strategy类的引用,用一个ConcreteStrategy对象来配置
适用性
- 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法
- 需要使用一个算法的不同变体。
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的,与算法相关的数据结构
- 一个类定义了多种行为,并且 这些行为在这个类的操作中以多个形式出现。将相关的条件分支移和它们各自的Strategy类中以代替这些条件语句
类图
实例
|
|
优缺点
优点
- 策略模式提供了管理相关的算法族的办法
- 策略模式提供了可以替换继承关系的办法 将算封闭在独立的Strategy类中使得你可以独立于其Context改变它
- 使用策略模式可以避免使用多重条件转移语句。
缺点
- 客户必须了解所有的策略 这是策略模式一个潜在的缺点
- Strategy和Context之间的通信开销
- 策略模式会造成很多的策略类
参考
命令模式(Command pattern)
命令模式是一种行为型模式,它将一个请求封装为一个对象,从而使用你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
主要角色
- 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。
- 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执行方法。
- 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
- 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
- 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
适用性
- 抽象出待执行的动作以参数化对象。Command模式是回调机制的一个面向对象的替代品。
- 在不同的时刻指定、排列和执行请求。
- 支持取消操作。
- 支持修改日志。
- 用构建在原语操作上的高层操作构造一个系统。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。
类图
实例
|
|
优缺点
优点
- 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。
- 命令类与其他任何别的类一样,可以修改和推广。
- 可以把命令对象聚合在一起,合成为合成命令。
- 可以很容易的加入新的命令类。
缺点
- 可能会导致某些系统有过多的具体命令类。
参考
解释器模式(Interpreter pattern)
解释器模式是一种行为型模式,它给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
类图
实例
|
|
参考
迭代器模式(Iterator pattern)
迭代器模式是一种行为型模式,它是一种最简单也最常见的设计模式。它可以让使用者透过特定的接口巡访容器中的每一个元素而不用了解底层的实作。
适用性
- 在希望利用语言本身的遍历函数便利自定义结构时,例如PHP中的foreach函数
实例
|
|
参考
中介者模式(Mediator pattern)
中介者模式是一种行为型模式,它包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
主要角色
- 中介者(Mediator)角色:定义了对象间相互作用的接口
- 具体中介者(ConcreteMediator)角色:实现了中介者定义的接口。
- 具体对象(ConcreteColleague)角色:通过中介者和别的对象进行交互
实例
|
|
参考
备忘录模式(Memento pattern)
备忘录模式是一种行为型模式,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样可以在以后把该对象的状态恢复到之前保存的状态。
主要角色
- 备忘录(Memento)角色:存储发起人(Originator)对象的内部状态,而发起人根据需要决定备忘录存储发起人的哪些内部状态。备忘录可以保护其内容不被发起人(Originator)对象之外的任何对象所读取。
- 发起人(Originator)角色:创建一个含有当前的内部状态的备忘录对象,使用备忘录对象存储其内部状态
- 负责人(Caretaker)角色:负责保存备忘录对象,不检查备忘录对象的内容
适用性
- 必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
- 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
类图
实例
|
|
优缺点
优点
- 有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取。
- 简化了发起人(Originator)类。发起人(Originator)不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理它们所需要的这些状态的版本
- 当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
缺点
- 如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
- 当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否会很昂贵。
- 当发起人角色的状态改变的时候,有可能这个状态无效。
参考
访问者模式(Visitor pattern)
访问者模式是一种行为型模式,访问者表示一个作用于某对象结构中各元素的操作。它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者角色。
访问者模式利用了双重分派。先将访问者传入元素对象的Accept方法中,然后元素对象再将自己传入访问者,之后访问者执行元素的相应方法。
主要角色
- 抽象访问者角色(Visitor):为该对象结构(ObjectStructure)中的每一个具体元素提供一个访问操作接口。该操作接口的名字和参数标识了 要访问的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
- 具体访问者角色(ConcreteVisitor):实现抽象访问者角色接口中针对各个具体元素角色声明的操作。
- 抽象节点(Node)角色:该接口定义一个accept操作接受具体的访问者。
- 具体节点(Node)角色:实现抽象节点角色中的accept操作。
- 对象结构角色(ObjectStructure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合(在PHP中我们使用数组代替,因为PHP中的数组本来就是一个可以放置任何类型数据的集合)
适用性
- 访问者模式多用在聚集类型多样的情况下。在普通的形式下必须判断每个元素是属于什么类型然后进行相应的操作,从而诞生出冗长的条件转移语句。而访问者模式则可以比较好的解决这个问题。对每个元素统一调用$element->accept($vistor)即可。
- 访问者模式多用于被访问的类结构比较稳定的情况下,即不会随便添加子类。访问者模式允许被访问结构添加新的方法。
类图
实例
|
|
优缺点
优点
- 访问者模式使得增加新的操作变得很容易。使用访问者模式可以在不用修改具体元素类的情况下增加新的操作。它主要是通过元素类的accept方法来接受一个新的visitor对象来实现的。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
- 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
- 访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
- 积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。
缺点
- 增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
- 破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
参考
策略模式(Strategy pattern)
状态模式是一种行为型模式,它允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类,状态模式变化的位置在于对象的状态。
主要角色
- 抽象状态(State)角色:定义一个接口,用以封装环境对象的一个特定的状态所对应的行为
- 具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为
- 环境(Context)角色:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态
适用性
- 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式模式将每一个条件分支放入一个独立的类中。这使得你可以要所对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化
类图
实例
|
|
优缺点
优点
- 它将与特定状态相关的行为局部化
- 它使得状态转换显示化
- State对象可被共享
参考
抽象工厂模式(Abstract Factory pattern)
抽象工厂模式是一种创建型模式,它提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。它的实质是“提供接口,创建一系列相关或独立的对象,而不指定这些对象的具体类”。
抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂模式中主要角色
- 抽象工厂(Abstract Factory)角色:它声明创建抽象产品对象的接口
- 具体工厂(Concrete Factory)角色:实现创建产品对象的操作
- 抽象产品(Abstract Product)角色:声明一类产品的接口
- 具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口
这个和工厂方法模式类似,我们不再只要一个汉堡,可能是4个汉堡2个鸡翅,我们还是对服务员说,服务员属于具体工厂,抽象产品就是麦当劳可卖的食物,具体产品是我们跟服务员要的食物。
适用性
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 需要强调一系列相关的产品对象的设计以便进行联合使用时。
- 提供一个产品类库,而只想显示它们的接口而不是实现时。
类图
实例
|
|
在这里例子中,工厂类实现了一组工厂方法。如果要增加新的功能,可以增加新的接口,让新的工厂类实现这个接口即可,而无需修改现有的工厂类。
优缺点
优点
- 分离了具体的类
- 使增加或替换产品族变得容易
- 有利于产品的一致性
缺点
难以支持新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新各类的产品就需要扩展访工厂接口,从而导致AbstractFactory类及其所有子类的改变。
参考
工厂方法模式(Factory method pattern)
工厂方法模式是一种创建型模式,这种模式使用“工厂”概念来完成对象的创建而不用具体说明这个对象。
在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。
主要角色
- 抽象产品(Product)角色:具体产品对象共有的父类或者接口。
- 具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口
- 抽象工厂(Creator)角色:它声明了工厂方法,该方法返回Product对象
- 具体工厂(Concrete Creator):实现抽象工厂接口
工厂方法模式就像我们去麦当劳买汉堡,我们只要找到服务员,让他帮我们拿来汉堡即可。其中具体某个服务员就像具体工厂,他继承了服务员应有的服务。汉堡在到手以前属于抽象产品,而我们拿到的汉堡就属于具体产品。
适用性
- 创建对象需要大量重复的代码(例如创建一个MySQL操作类,需要配置很多选项,这些都可以在工厂方法中进行)。
- 创建对象需要访问某些信息,而这些信息不应该包含在复合类中。
- 创建对象的生命周期必须集中管理,以保证在整个程序中具有一致的行为。
类图
实例
普通工厂方法
下面的例子是工厂方法模式的应用,我们要创建两种风格的按钮,只需用不同的工厂方法获得相应按钮类即可。
|
|
上例中的createButton()
方法即所谓的工厂方法,它所在的类仅仅是这个方法的载体。工厂方法的核心功能是创建类并返回,这个方法可以产生一个类,也可以产生多种类。这个方法本身的载体也并不局限,将其设置为静态方法也是可以的,这个根据自己的情况而定。
优缺点
优点
工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
缺点
- 重构已经存在的类会破坏客户端代码。
- 如果工厂方法所在类的构造函数为私有,则工厂方法无法继续扩展,或者必须实现工厂方法所在类的全部依赖方法。
参考
模板方法模式(Template method pattern)
模板方法模式模式是一种行为型模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以在不改变一个算法的结构的情况下重定义该算法的某些特定的步骤。
主要角色
抽象模板(AbstractClass)角色
定义一个或多个抽象方法让子类实现。这些抽象方法叫做基本操作,它们是顶级逻辑的组成部分。
定义一个模板方法。这个模板方法一般是一个具体方法,它给出顶级逻辑的骨架,而逻辑的组成步骤在对应的抽象操作中,这些操作将会推迟到子类中实现。同时,顶层逻辑也可以调用具体的实现方法
具体模板(ConcrteClass)角色
实现父类的一个或多个抽象方法,作为顶层逻辑的组成而存在。
每个抽象模板可以有多个具体模板与之对应,而每个具体模板有其自己对抽象方法(也就是顶层逻辑的组成部分)的实现,从而使得顶层逻辑的实现各不相同。
适用性
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
- 控制子类扩展。
类图
实例
|
|
参考
责任链模式(Chain of responsibility pattern)
责任链模式是一种行为型模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。
主要角色
- 抽象责任(Responsibility)角色:定义所有责任支持的公共方法。
- 具体责任(Concrete Responsibility)角色:以抽象责任接口实现的具体责任
- 责任链(Chain of responsibility)角色:设定责任的调用规则
实例
|
|
参考
Git 常用资源
历史管理
查看历史
git log --pretty=oneline filename // 一行显示
git show xxxx // 查看某次修改
标签功能
git tag // 显示所有标签
git tag -l 'v1.4.2.*' // 显示 1.4.2 开头标签
git tag v1.3 // 简单打标签
git tag -a v1.2 9fceb02 // 后期加注标签
git tag -a v1.4 -m 'my version 1.4' // 增加标签并注释, -a 为 annotated 缩写
git show v1.4 // 查看某一标签详情
git push origin v1.5 // 分享某个标签
git push origin --tags // 分享所有标签
回滚操作
reset --hard v0.1
reflog
reset --hard v0.2
取消某个文件的修改
git checkout -- <filename>
删除文件
git rm <filename> 直接删除文件
git rm --cached <filename> 删除文件暂存状态
移动文件
git mv <sourcefile> <destfile>
查看文件更新
git diff 查看未暂存的文件更新
git diff --cached 查看已暂存文件的更新
分支管理
创建分支
git branch develop // 只创建分支
git checkout -b master develop // 创建并切换到 develop 分支
合并分支
git checkout master // 切换到主分支
git merge --no-ff develop // 把 develop 合并到 master 分支,no-ff 选项的作用是保留原分支记录
git rebase develop // 合并分支
git branch -d develop // 删除 develop 分支
克隆远程分支
git branch -r
git checkout origin/android
修复develop上的合并错误
- 将merge前的commit创建一个分之,保留merge后代码
- 将develop
reset --force
到merge前,然后push --force
- 在分支中rebase develop
- 将分支push到服务器上重新merge
Submodule使用
克隆带submodule的库
git clone --recursive https://github.com/chaconinc/MainProject
clone主库后再去clone submodule
git clone https://github.com/chaconinc/MainProject
git submodule init
git submodule update
Git设置
Git的全局设置在~/.gitconfig
中,单独设置在project/.git/config
下。
忽略设置全局在~/.gitignore_global
中,单独设置在project/.gitignore
下。
设置 commit 的用户和邮箱
|
|