PHP中常用的几种设计模式
1.工厂模式
工厂模式是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建对象,而不直接使用 new
。这样,如果您想要更改所创建的对象类型,只需更改该工厂即可。使用该工厂的所有代码会自动更改。
07 | class User implements IUser |
09 | public function __construct( $id ) { } |
11 | public function getName() |
19 | public static function Create( $id ) |
21 | return new User( $id ); |
25 | $uo = UserFactory::Create( 1 ); |
26 | echo ( $uo ->getName(). "/n" ); |
另一种更简洁的工厂模式:
07 | class User implements IUser |
09 | public static function Load( $id ) |
11 | return new User( $id ); |
14 | public static function Create( ) |
16 | return new User( null ); |
19 | public function __construct( $id ) { } |
21 | public function getName() |
27 | $uo = User::Load( 1 ); |
28 | echo ( $uo ->getName(). "/n" ); |
2、单元素模式:
某些应用程序资源是独占的,因为有且只有一个此类型的资源。例如,通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销,在获取单个页面的过程中更是如此。
单元素模式可以满足此要求。如果应用程序每次包含且仅包含一个对象,那么这个对象就是一个单元素(Singleton)。清单 3 中的代码显示了 PHP V5 中的一个数据库连接单元素。
您可以使用全局变量存储数据库句柄,但是,该方法仅适用于较小的应用程序。在较大的应用程序中,应避免使用全局变量,并使用对象和方法访问资源。
02 | require_once ( "DB.php" ); |
04 | class DatabaseConnection |
06 | public static function get() |
10 | $db = new DatabaseConnection(); |
14 | private $_handle = null; |
16 | private function __construct() |
19 | $this ->_handle =& DB::Connect( $dsn , array () ); |
22 | public function handle() |
24 | return $this ->_handle; |
28 | print ( "Handle = " .DatabaseConnection::get()->handle(). "/n" ); |
29 | print ( "Handle = " .DatabaseConnection::get()->handle(). "/n" ); |
3、观察者模式
观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。
一个简单示例是系统中的用户列表。清单 4 中的代码显示一个用户列表,添加用户时,它将发送出一条消息。添加用户时,通过发送消息的日志观察者可以观察此列表。
04 | function onChanged( $sender , $args ); |
09 | function addObserver( $observer ); |
12 | class UserList implements IObservable |
14 | private $_observers = array (); |
16 | public function addCustomer( $name ) |
18 | foreach ( $this ->_observers as $obs ) |
19 | $obs ->onChanged( $this , $name ); |
22 | public function addObserver( $observer ) |
24 | $this ->_observers []= $observer ; |
28 | class UserListLogger implements IObserver |
30 | public function onChanged( $sender , $args ) |
32 | echo ( "'$args' added to user list/n" ); |
36 | class UserListLogger2 implements IObserver |
38 | public function onChanged( $sender , $args ) |
40 | echo ( "'$args' 2222222222222222 list/n" ); |
45 | $ul ->addObserver( new UserListLogger() ); |
46 | $ul ->addObserver( new UserListLogger2() ); |
47 | $ul ->addCustomer( "Jack" ); |
4、命令链模式
命令链模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。
总体来说命令链模式就是让系统定义多个执行接口,而通过一个命令链接口来执行!
04 | function onCommand( $name , $args ); |
09 | private $_commands = array (); |
11 | public function addCommand( $cmd ) |
13 | $this ->_commands []= $cmd ; |
16 | public function runCommand( $name , $args ) |
18 | foreach ( $this ->_commands as $cmd ) |
20 | if ( $cmd ->onCommand( $name , $args ) ) |
26 | class UserCommand implements ICommand |
28 | public function onCommand( $name , $args ) |
30 | if ( $name != 'addUser' ) return false; |
31 | echo ( "UserCommand handling 'addUser'/n" ); |
36 | class MailCommand implements ICommand |
38 | public function onCommand( $name , $args ) |
40 | if ( $name != 'mail' ) return false; |
41 | echo ( "MailCommand handling 'mail'/n" ); |
46 | $cc = new CommandChain(); |
47 | $cc ->addCommand( new UserCommand() ); |
48 | $cc ->addCommand( new MailCommand() ); |
49 | $cc ->runCommand( 'addUser' , null ); |
50 | $cc ->runCommand( 'mail' , null ); |
5、策略模式
我们讲述的最后一个设计模式是策略模式。在此模式中,算法是从复杂类提取的,因而可以方便地替换。例如,如果要更改搜索引擎中排列页的方法,则策略模式是一个不错的选择。思考一下搜索引擎的几个部分部分遍历页面,一部分对每页排列,另一部分基于排列的结果排序。在复杂的示例中,这些部分都在同一个类中。通过使用策略模式,您可将排列部分放入另一个类中,以便更改页排列的方式,而不影响搜索引擎的其余代码。
04 | function filter( $record ); |
07 | class FindAfterStrategy implements IStrategy |
11 | public function __construct( $name ) |
16 | public function filter( $record ) |
18 | return strcmp ( $this ->_name, $record ) <= 0; |
22 | class RandomStrategy implements IStrategy |
24 | public function filter( $record ) |
26 | return rand( 0, 1 ) >= 0.5; |
32 | private $_list = array (); |
34 | public function __construct( $names ) |
38 | foreach ( $names as $name ) |
40 | $this ->_list []= $name ; |
45 | public function add( $name ) |
47 | $this ->_list []= $name ; |
50 | public function find( $filter ) |
53 | foreach ( $this ->_list as $user ) |
55 | if ( $filter ->filter( $user ) ) |
62 | $ul = new UserList( array ( "Andy" , "Jack" , "Lori" , "Megan" ) ); |
63 | $f1 = $ul ->find( new FindAfterStrategy( "J" ) ); |
66 | $f2 = $ul ->find( new RandomStrategy() ); |