Better construction of five PHP design patterns for development templates, better construction of five PHP design patterns for development templates, the design patterns are only prepared for Java architects-at least you may always think so. In fact, the design pattern is very useful to everyone. If these tools are not the patents of the "architecture astronauts", what are they? Why do you say "> <LINKhref =" http: // www. php1 design pattern is only prepared for the Java architect-at least you may always think so. In fact, the design pattern is very useful to everyone. If these tools are not the patents of the "architecture astronauts", what are they? Why are they very useful in PHP applications? This article explains these issues.
The Design patterns book introduces Design patterns to the software community by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides Design (commonly known as the "four-person gang "). The core concept behind the design pattern is very simple. After years of software development practices, Gamma and others have discovered some patterns of fixed design. just like architects designing houses and buildings, they can develop templates for bathroom locations or kitchen structures. Using these templates or design patterns means faster building design. The same concept applies to software.
The design pattern not only represents a useful way to develop robust software faster, but also provides a method to encapsulate large concepts in friendly terms. For example, you can say that you are writing a message transmission system that provides loose coupling, or you are writing a mode named observer.
It is very difficult to use small examples to demonstrate the value of the model. This is often a little practical, because the model actually plays a role in large code libraries. This article does not show large applications, so you need to think about how to apply the sample principles in your own large applications-rather than the code demonstrated in this article. This does not mean that you should not use the mode in a small application. Many good applications are developed from small applications to large applications, so there is no reason not to base on such solid coding practices. Now that you know the design patterns and their usefulness, let's take a look at the five common patterns of PHP V5.
Factory model
Many design patterns encourage loose coupling in the design patterns book. To understand this concept, we 'd better talk about the hard work of many developers engaged in large-scale systems. A problem occurs when you change a code snippet. other parts of the system, which you once thought were completely unrelated, may also cause cascading damages.
This problem lies in tight coupling. Functions and classes in a certain part of the system depend heavily on the behavior and structure of functions and classes in other parts of the system. You need a set of modes to enable these classes to communicate with each other, but do not want to closely bind them together to avoid interlocking. In large systems, many codes depend on a few key classes. It may be difficult to change these classes. For example, assume that you have a User class to read from a file. You want to change it to other classes read from the database, but all code references the original class read from the file. At this time, it is very convenient to use the factory model.
Factory mode is a type that provides methods for creating objects for you. You can use the factory class to create objects instead of using new directly. In this way, if you want to change the type of the created object, you only need to change the factory. All codes used in the factory are automatically changed.
Listing 1 shows an indication column of the factory class. The server side of the equation consists of a database and a set of PHP pages that allow you to add feedback, request feedback lists, and obtain articles related to specific feedback.
Listing 1. Factory1.php
<? Php Interface IUser { Function getName (); }
Class User implements IUser { Public function _ construct ($ id ){}
Public function getName () { Return "Jack "; } }
Class UserFactory { Public static function Create ($ id) { Return new User ($ id ); } }
$ Uo = UserFactory: Create (1 ); Echo ($ uo-> getName (). "\ n "); ?> |
The IUser interface defines what operations a user object should perform. The implementation of IUser is called User, and the UserFactory class creates an IUser object. This relationship can be expressed in UML in figure 1.
Figure 1. factory class and related IUser interface and user class |
If you use the php interpreter to run this code on the command line, the following result is displayed:
The test code will request the User object to the factory and output the result of the getName method.
There is a variation in the factory model that uses the Factory method. Class. This method is useful when you create an object of this type. For example, suppose you need to create an object first and then set many attributes. The factory mode of this version encapsulates the process in a single location, so that you do not need to copy complicated initialization code or paste the copied code everywhere in the code base. Listing 2 shows an example of using the factory method.
Listing 2. Factory2.php
<? Php Interface IUser { Function getName (); }
Class User implements IUser { Public static function Load ($ id) { Return new User ($ id ); }
Public static function Create () { Return new User (null ); }
Public function _ construct ($ id ){}
Public function getName () { Return "Jack "; } }
$ Uo = User: Load (1 ); Echo ($ uo-> getName (). "\ n "); ?> |
This code is much simpler. It only has one IUser interface and one User class that implements this interface. The User class has two static methods for creating objects. This link can be expressed in UML in figure 2.
Figure 2. IUser interface and user class with factory method |
The result of running the script in the command line is the same as that in listing 1, as shown below:
As mentioned above, sometimes such models seem to be a little useful in a small environment. However, it is best to learn this solid coding format to apply it to any scale of projects.
Single element mode
Some application resources are exclusive because there is only one resource of this type. For example, the connection from a database handle to a database is exclusive. You want to share the database handle in the application, because it is an overhead when you keep the connection open or closed, especially when you get a single page.
The single-element mode can meet this requirement. If an application contains only one object each time, the object is a Singleton ). The code in listing 3 shows a single database connection element in PHP V5.
Listing 3. Singleton. php
<? Php Require_once ("DB. php ");
Class DatabaseConnection { Public static function get () { Static $ db = null; If ($ db = null) $ Db = new DatabaseConnection (); Return $ db; }
Private $ _ handle = null; Private function _ construct () { $ Dsn = 'MySQL: // root: password @ localhost/photos '; $ This-> _ handle = & DB: Connect ($ dsn, array ()); }
Public function handle () { Return $ this-> _ handle; } }
Print ("Handle =". DatabaseConnection: get ()-> handle (). "\ n "); Print ("Handle =". DatabaseConnection: get ()-> handle (). "\ n "); ?> |
This code displays a single class named DatabaseConnection. You cannot create your own DatabaseConnection because the constructor is dedicated. However, with the static get method, you can obtain only one DatabaseConnection object. This code is shown in UML 3.
Figure 3. database connection ticket elements |
In the two calls, the database handle returned by the handle method is the same, which is the best proof. You can run the code in the command line to observe this point.
% Php singleton. php Handle = Object id #3 Handle = Object id #3 % |
The two handles returned are the same object. If you use a single database connection element in the entire application, you can reuse the same handle anywhere.
You can use global variables to store database handles. However, this method is only applicable to small applications. In large applications, avoid using global variables and use objects and methods to access resources.
Observer Mode
The Observer Mode provides another way to avoid close coupling between components. This mode is very simple: an object becomes observability by adding a method (this method allows another object, that is, the Observer registers itself. When an observed object changes, the message is sent to the registered observer. The operations performed by these observers using this information are irrelevant to the observed objects. The result is that objects can communicate with each other without understanding the cause. A simple example is the user list in the system. The code in listing 4 shows a user list. when a user is added, it sends a message. When a user is added, the list can be observed by the log observer who sends the message.
Listing 4. Observer. php
<? 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 "); ?> |
This code defines four elements: two interfaces and two classes. The IObservable interface defines the objects that can be observed. UserList implements this interface to register itself as an observed object. The IObserver list defines how to become an observer, and UserListLogger implements the IObserver interface. The elements are shown in UML in figure 4.
Figure 4. observed user list and user list event log programs |
If you run it in the command line, you will see the following output:
% Php observer. php 'Jack' added to user list % |
Test code to create a UserList and add the UserListLogger observer to it. Then add a consumer and notify UserListLogger of this change.
It is critical to realize that the UserList does not know what operations the log program will perform. One or more listeners may execute other operations. For example, you may have an observer who sends messages to a new user. You are welcome to use this system. The value of this method is that UserList ignores all objects dependent on it. it focuses on maintaining the user list and sending messages when the list is changed.
This mode is not limited to objects in memory. It is the basis for database-driven message query systems used in large applications.
Command chain mode
The command chain mode sends messages, commands, and requests based on loosely coupled topics, or sends arbitrary content through a set of handlers. Each handler determines whether it can process the request. If yes, the request is processed and the process stops. You can add or remove a handler for the system without affecting other handlers. Listing 5 shows an example of this mode.
Listing 5. Chain. php
<? Php Interface ICommand { Function onCommand ($ name, $ args ); }
Class CommandChain { Private $ _ commands = array ();
Public function addCommand ($ cmd) { $ This-> _ commands [] = $ cmd; }
Public function runCommand ($ name, $ args) { Foreach ($ this-> _ commands as $ cmd) { If ($ cmd-> onCommand ($ name, $ args )) Return; } } }
Class UserCommand implements ICommand { Public function onCommand ($ name, $ args) { If ($ name! = 'Adduser') return false; Echo ("UserCommand handling 'adduser' \ n "); Return true; } }
Class MailCommand implements ICommand { Public function onCommand ($ name, $ args) { If ($ name! = 'Mail') return false; Echo ("MailCommand handling 'mail' \ n "); Return true; } }
$ Cc = new CommandChain (); $ Cc-> addCommand (new UserCommand ()); $ Cc-> addCommand (new MailCommand ()); $ Cc-> runCommand ('adduser', null ); $ Cc-> runCommand ('mail', null ); ?> |
This code defines the CommandChain class that maintains the list of ICommand objects. Both classes can implement the ICommand interface-one responding to the Mail request and the other responding to the added user. Figure 5 shows the UML.
Figure 5. command chain and related commands |
If you run a script containing some test code, the following output is displayed:
% Php chain. php UserCommand handling 'adduser' MailCommand handling 'mail' % |
The code first creates a CommandChain object and adds instances of two command objects to it. Then run two commands to check who has responded to these commands. If the command name matches UserCommand or MailCommand, the code fails without any operation. When creating a scalable architecture for request processing, the command chain mode is very valuable and can solve many problems.
Rule mode
The last design pattern we talk about is the strategy pattern. In this mode, algorithms are extracted from complex classes and can be easily replaced. For example, if you want to change the page arrangement method in the search engine, the policy mode is a good choice. Think about the several parts of the search engine-one part traverses the page, the other part sorts each page, and the other part sorts the results based on the arrangement. In a complex example, these parts are in the same class. By using the policy mode, you can place the arranged parts into another class to change the page arrangement method without affecting the rest of the search engine code.
As a simple example, listing 6 shows a user list class, which provides a method for finding a group of users based on a set of plug-and-play policies.
Listing 6. Strategy. php
<? Php Interface IStrategy { Function filter ($ record ); }
Class FindAfterStrategy implements IStrategy { Private $ _ name;
Public function _ construct ($ name) { $ This-> _ name = $ name; }
Public function filter ($ record) { Return strcmp ($ this-> _ name, $ record) <= 0; } }
Class RandomStrategy implements IStrategy { Public function filter ($ record) { Return rand (0, 1) >=0.5; } }
Class UserList { Private $ _ list = array ();
Public function _ construct ($ names) { If ($ names! = Null) { Foreach ($ names as $ name) { $ This-> _ list [] = $ name; } } }
Public function add ($ name) { $ This-> _ list [] = $ name; }
Public function find ($ filter) { $ Recs = array (); Foreach ($ this-> _ list as $ user) { If ($ filter-> filter ($ user )) $ Recs [] = $ user; } Return $ recs; } }
$ Ul = new UserList (array ("Andy", "Jack", "Lori", "Megan ")); $ F1 = $ ul-> find (new FindAfterStrategy ("J ")); Print_r ($ f1 );
$ F2 = $ ul-> find (new RandomStrategy ()); Print_r ($ f2 ); ?> |
Figure 6. user list and user selection policy |
The UserList class is a package for packaging name arrays. It implements the find method. this method selects a subset of these names using one of several policies. These policies are defined by the IStrategy interface, which has two implementations: one randomly selects the user and the other selects all the subsequent names based on the specified name. When you run the test code, the following output is displayed:
% Php strategy. php Array ( [0] => Jack [1] => Lori [2] => Megan ) Array ( [0] => Andy [1] => Megan ) % |
The test code runs the same user list for two policies and displays the results. In the first case, the policy looks for any name after J, so you will get Jack, Lori, and Megan. The second policy selects a random name and produces different results each time. In this case, the result is Andy and Megan.
The rule mode is very suitable for complex data management systems or data processing systems. The two require high flexibility in data filtering, search, or processing methods.
Conclusion
This article only describes several of the most common design patterns used in PHP applications. The book on design patterns demonstrates more design patterns. Do not give up because the architecture is mysterious. Pattern is a wonderful concept, applicable to any programming language, any skill level.