即使我写了这样的文章,我依然坚信设计模式只是某些垃圾语言用来规避其语言本身弊端的规范而已,不然,就只能写出糟糕的代码了。
创建型 Factory Method(工厂方法模式/工厂模式) 工厂模式是一种类,提供了创建对象的某些方法,可以直接使用工厂类创建对象,而不是直接使用new。
优点:如果要改变所创建对象的类型,只需要修改该工厂即可。比如有个类需要读取用户数据来创建,原本是读取的数据库,现在要从文本读取,就得把那个类及其所有依赖都更改一遍。
php示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php interface IPost { function getName ( ) ; } class Post implements IPost { public function __construct ($id ) {} public static function Load ($id ) { return new Post ($id ); } public static function Create ( ) { return new Post (null ); } public function getName ( ) { return "haofly" ; } } $post = Post ::Load (1 );echo $post ->getName ();?>
AbstractFactory(抽象工厂模式) 抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。
php示例,代码来自维基百科
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 <?php abstract class AbstractFactory { abstract public function CreateButton ( ) ; abstract public function CreateBorder ( ) ; } class MacFactory extends AbstractFactory { public function CreateButton ( ) { return new MacButton (); } public function CreateBorder ( ) { return new MacBorder (); } } class WinFactory extends AbstractFactory { public function CreateButton ( ) { return new WinButton (); } public function CreateBorder ( ) { return new WinBorder (); } } class Button {}class Border {}class MacButton extends Button { function __construct ( ) { echo 'MacButton is created' . "\n" ; } } class MacBorder extends Border { function __construct ( ) { echo 'MacBorder is created' . "\n" ; } } class WinButton extends Button { function __construct ( ) { echo 'WinButton is created' . "\n" ; } } class WinBorder extends Border { function __construct ( ) { echo 'WinBorder is created' . "\n" ; } } ?> <? $type = 'Mac' ; if (!in_array ($type , array ('Win' ,'Mac' ))) die ('Type Error' ); $factoryClass = $type .'Factory' ;$factory =new $factoryClass ;$factory ->CreateButton ();$factory ->CreateBorder ();?>
Prototype(原型模式) 通过复制一个已经存在的实例来返回新的实例,而不是新建实例。
优点: 多用于创建复杂的或者耗时的实例,这种情况,复制一个已经存在的实例使程序运行更高效,活着创建值相等,只是命名不一样的同类数据。
Singleton(单例模式) php示例,代码来自IBM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php require_once ("DB.php" );class DatabaseConnectiono { private $_handle = null ; private function __construct ( ) { $dsn = 'mysql://root:password@localhost/photos' ; $this ->_handle = & DB::Connect ($dsn , array ()); } public static function get ( ) { static $db = null ; if ($db == null ) $db = new DatabaseConnectioni (); return $db ; } public function handle ( ) { return $this ->_handle; } } print ("Handle=" .DatabaseConnection ::get ()->handle ()."\n" );print ("Handle=" .DatabaseConnection ::get ()->handle ()."\n" );
结构型 Adapter Class/Object(适配器/转换器) 介绍: 把一个类的接口变换成客户端所期待的另一种接口,Adapter模式使原本因接口不匹配或不兼容而无法在一起工作的两个类能够在一起工作。外部请求方式一样,内部实现方式不一样。
应用场景:
想使用一个已经存在的类,但是它的接口并不完全符合需求
适用于第三方库的API会发生改变而选择不直接把第三方API给用户使用的情况下,在前面封装一层。
php实例,代码来自真实的归宿
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 <?php interface Target { public function hello ( ) ; public function world ( ) ; } class Adapter { public function world ( ) { echo ' world <br />' ; } public function greet ( ) { echo ' Greet ' ; } } class Adapter implements Target { private $_adaptee ; public function __construct (Adaptee $adaptee ) { $this ->_adaptee = $adaptee ; } public function hello ( ) { $this ->_adaptee->greet (); } } class Client { public static function main ( ) { $adaptee = new Adaptee (); $adapter = new Adapter ($adaptee ); $adapter ->hello (); $adapter ->world (); } } Client ::main (); ?>
Bridge(桥接模式) 把事务对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。
python实例,代码来自维基百科
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 """圆形、三角形归于抽象的形状,而画圆、画三角形归于抽象的画图""" class DrawingAPI : def drawCircle (x, y, radius ): pass class DrawingAPI1 (DrawingAPI ): def drawCircle (self, x, y, radius ): print "API1.circle at %f:%f radius %f" % (x, y, radius) class DrawingAPI2 (DrawingAPI ): def drawCircle (self, x, y, radius ): print "API2.circle at %f:%f radius %f" % (x, y, radius) class Shape : def draw (self ): pass def resizeByPercentage (self, pct ): pass class CircleShape (Shape ): def __init__ (self, x, y, radius, drawingAPI ): self.__x = x self.__y = y self.__radius = radius self.__drawingAPI = drawingAPI def draw (self ): self.__drawingAPI.drawCircle(self.__x, self.__y, self.__radius) def resizeByPercentage (self, pct ): self.__radius *= pct def main (): shapes = [ CircleShape(1 , 2 , 3 , DrawingAPI1()), CircleShape(5 , 7 , 11 , DrawingAPI2()) ] for shape in shapes: shape.resizeByPercentage(2.5 ) shape.draw() if __name__ == "__main__" : main()
Composite(组合模式) Decorator(装饰模式) Facade(外观) Flywight(享元) Proxy(代理) 行为型 Interpreter(解释器) Template Method(模板方法) Observer(观察者模式) 优点: 被观察对象不用具体了解观察者具体实现,而是由观察者去实现。被观察者忽略了依赖它的对象,它要关注在事件发生时触发该事件并发送消息给观察者即可。这个和依赖注入有点相近的地方。
php示例,代码来自IBM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?php interface IObserver { function onChanged ($sender , $args ) ; } interface IObservable { function addObserver ($observer ) ; } class UserList implements IObservable { private $_observers = array (); public function addCustomer ($name ) { foreach ($this ->_observers as $obs ){ $obs ->onChanged ($this , $name ); } } public function addObserver ($observer ) { $this ->_observers[] = $observer ; } } class UserListLogger implements IOBserver { public function onChanged ($sender , $args ) { echo ("'$args ' added to user list\n" ); } } $ul = new UserList ();$ul ->addObserver (new UserListLogger ());$ul ->addCustomer ("Jack" );
Command(命令) Chain of Respopnsibility(责任链) 包含了一些命令对象和一系列的处理对象,每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。
php示例,代码来自维基百科
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 <?php abstract class Logger { const ERR = 3 ; const NOTICE = 5 ; const DEBUG = 7 ; protected $mask ; protected $next ; public function setNext (Logger $l ) { $this ->next = $l ; return $this ; } abstract public function message ($msg , $priority ) ; } class DebugLogger extends Logger { public function __construct ($mask ) { $this ->mask = $mask ; } public function message ($msg , $priority ) { if ($priority <= $this ->mask) { echo "Writing to debug output: {$msg} \n" ; } if (false == is_null ($this ->next)) { $this ->next->message ($msg , $priority ); } } } class EmailLogger extends Logger { public function __construct ($mask ) { $this ->mask = $mask ; } public function message ($msg , $priority ) { if ($priority <= $this ->mask) { echo "Sending via email: {$msg} \n" ; } if (false == is_null ($this ->next)) { $this ->next->message ($msg , $priority ); } } } class StderrLogger extends Logger { public function __construct ($mask ) { $this ->mask = $mask ; } public function message ($msg , $priority ) { if ($priority <= $this ->mask) { echo "Writing to stderr: {$msg} \n" ; } if (false == is_null ($this ->next)) { $this ->next->message ($msg , $priority ); } } } class ChainOfResponsibilityExample { public function __construct ( ) { $l = new DebugLogger (Logger ::DEBUG ); $e = new EmailLogger (Logger ::NOTICE ); $s = new StderrLogger (Logger ::ERR ); $e ->setNext ($s ); $l ->setNext ($e ); $l ->message ("Entering function y." , Logger ::DEBUG ); $l ->message ("Step1 completed." , Logger ::NOTICE ); $l ->message ("An error has occurred." , Logger ::ERR ); } } new ChainOfResponsibilityExample ();?>
Iterator(迭代器) Memento(备忘录) State(状态) Strategy(策略模式) 指对象有某种行为,但是在不同的场景中,该行为有不同的实现算法。
抽象工厂与策略模式不同的地方在于,工厂是创建型模式,关注的是对象的创建,而策略是行为型模式,关注的是对行为的封装,对于工厂来说无论返回的对象内部是怎样的,只要是我想要的对象就行,而对于策略模式来说返回的对象即使不同也会有相同的方法/行为。
php示例,代码来自维基百科
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <?php class StrategyExample { public function __construct ( ) { $context = new Context (new ConcreteStrategyA ()); $context ->execute (); $context = new Context (new ConcreteStrategyB ()); $context ->execute (); $context = new Context (new ConcreteStrategyC ()); $context ->execute (); } } interface IStrategy { public function execute ( ) ; } class ConcreteStrategyA implements IStrategy { public function execute ( ) { echo "Called ConcreteStrategyA execute method\n" ; } } class ConcreteStrategyB implements IStrategy { public function execute ( ) { echo "Called ConcreteStrategyB execute method\n" ; } } class ConcreteStrategyC implements IStrategy { public function execute ( ) { echo "Called ConcreteStrategyC execute method\n" ; } } class Context { var $strategy ; public function __construct (IStrategy $strategy ) { $this ->strategy = $strategy ; } public function execute ( ) { $this ->strategy->execute (); } } new StrategyExample ;?>
Visitor(放问者) TroubleShooting