Previous review: "seven-day PHP framework" the next day: Model and database, click here
Original address: http://www.cnblogs.com/sweng/p/6624845.html, welcome attention: Programming Old man
Why use Design patterns?
Design patterns, my understanding is to achieve the "reusable" goal, and design a set of mutually collaborative classes.
Interested readers can read the design patterns:elements of reusable object-oriented software, with four authors (Gang of four) listing 23 of the industry's best-known patterns.
Here we first introduce the three design patterns that our framework will cover.
Singleton mode (singleton)
Singleton mode can guarantee that a class has only one object instance, which is commonly used in database access classes, thus saving the consumption of hardware resources.
Here, we rewrite the previous section of the MySQL class
123456789101112131415161718192021222324252627282930313233343536373839404142 |
class
MySQL
extends DB{
private
static
$instance
=null;
public
static
function
getInstance(){
if
(self::
$instance
==null){
self::
$instance
=
new
MySQL();
}
return
self::
$instance
;
}
public
function
MySQL(){
/*Config*/
$this
->IP=
‘*‘
;
$this
->ServerID=
‘*‘
;
$this
->ServerPassword=
‘*‘
;
$this
->DataBaseName=
‘*‘
;
/*End of Config*/
$this
->connection=mysqli_connect(
$this
->IP,
$this
->ServerID,
$this
->ServerPassword,
$this
->DataBaseName);
if
(!
$this
->connection){
die
(
‘Could not connect‘
.
$this
->connection);
}
mysqli_query(
$this
->connection,
‘set names utf8‘
);
}
public
function
Execute(
$sql
){
return
mysqli_query(
$this
->connection,
$sql
);
}
public
function
Query(
$sql
){
$result
=mysqli_query(
$this
->connection,
$sql
);
$arr
=
array
();
while
(
$row
=mysqli_fetch_array(
$result
)){
$arr
[]=
$row
;
}
return
$arr
;
}
public
function
Close(){
mysqli_close(
$this
->connection);
}
}
|
It is important to note that if you instantiate a MySQL class, we no longer write
But this:
1 |
$db =MySQL::getInstance(); |
Because only getinstance is a static function, the constructor of the MySQL class is guaranteed to be called only once.
Singleton mode is a very common design pattern, which is not mentioned here.
Appearance mode (facade)
Because of the namespace problem, the appearance pattern can guarantee that many methods of a class seem to be "provided by a class", where we first design a simple service provider class
12345 |
class ServiceProvider{ public function Write( $arg ){ echo $arg ; } } |
This class has only one write method, which is to print out the parameters
Then define a facade class
1234567891011121314 |
class
Facade{
public
static
function
getInstance(
$classname
,
$args
){
return
new
$classname
(
$args
);
}
public
static
function
getFacadeAccessor(){
//
}
public
static
function
__callstatic(
$method
,
$args
){
$instance
=
static
::getInstance(
static
::getFacadeAccessor(),
$args
);
return
call_user_func_array(
array
(
$instance
,
$method
),
$args
);
}
}
|
To understand this class, we just focus on the last function, the __callstatic magic method. This method is called the __callstatic method when the facade type object or its subclass calls a function that he does not define, and the method finally calls the Call_user_func_array function. is to give the task to the class that provides the service to complete, and to complete the transfer of parameters.
Let's write another facade subclass.
12345 |
class MyFacade extends Facade{ public static function getFacadeAccessor(){ return ServiceProvider:: class ; } } |
Notice here that the subclass implements the Getfacadeaccessor method that the parent class does not implement specifically, and this method is to tell the __callstatic method of the parent class: "What kind of class do I represent as a facade, the task is to be realized by him", from the grammatical point of view, Just returns a String representing the class name. So the parent does not know at first that its subclasses represent what "service provider class", only if the subclass's static function is called, because the subclass does not have the static function, so the __callstatic method of the parent class is started.
Abstract Factory (Factory)
I have a vulgar understanding of the abstract factory: "Object and string Correspondence", that is, a string can be used to create a class object. This approach is mostly useful in two situations:
1. Class name is not stable, will be frequently modified in the project
The class name modification, many times is not the designer "the name neat" or "the name Obsessive-Compulsive disorder" causes the modification, but in the project unceasing iteration, discovered this kind of design unreasonable. If this class is not used frequently, then change the class name as long as the manual to make some small changes, but if this class throughout the code (if it is a database class), the modification work is large, of course, we can also use the code file "string substitution", but if a PHP written project, PHP files are dozens of hundred, which is also unreasonable.
2. The designer of the class is not the user of the class
The designer of the class and the user of the class are not the same developers, so remembering a string may be more vivid than remembering a class name. We have all learned the principle of computer networks, all know that the memory of a domain name than the memory of an IP address to be more vivid, this is the problem of DNS resolution.
Because the abstract factory a lot of teaching materials are involved, no longer repeat, this article will introduce a very popular service container at present.
We hope that the whole project, DB class, Session class, FileSystem class, "Take to use", without each tedious initialization, such as write $db=new db (ARG1,ARG2), such statements, also want the DB and other types of objects like a "global" variable general, It can be called at any time during the entire program run.
The service container allows programmers of all types to call the DB without having to know the details of the class, or even create an object with an alias for the string.
We define a service container class
123456789 |
class
Container{
public
$bindings
;
public
function
bind(
$abstract
,
$concrete
){
$this
->bindings[
$abstract
]=
$concrete
;
}
public
function
make(
$abstract
,
$parameters
=[]){
return
call_user_func_array(
$this
->bindings[
$abstract
],
$parameters
);
}
}
|
The service container can be viewed simply as a global variable, and the Bind method is to bind strings and constructors with associative arrays.
Now, with the service container, our model class is going to be modified.
12345678910111213141516171819202122232425262728 |
class
Model
implements
IModel{
public
static $table
;
public
static
$container
;
public
static
$db
;
public
function
__construct(){
self::
$container
=
new Container();
self::
$container
->bind(
‘db‘
,
function
(){
return
MySQL::getInstance();
});
self::
$db
=self::
$container
->make(
‘db‘
,[]);
}
public
static
function
get(
$id
){
return
self::where(
‘id‘
,
$id
);
}
public
static
function
where(
$condition
,
$value
){
$sql
=sprintf(
"select * from %s where %s=‘%s‘"
,self::
$table
,
$condition
,
$value
);
return
self::
$db
->Query(
$sql
);
}
public
static
function
all(){
$sql
=sprintf(
"select * from %s"
,self::
$table
);
return
self::
$db
->Query(
$sql
);
}
}
|
Observing the code above, we used both a singleton pattern and a service container.
Summary: If you want to make a PHP framework, you should do a good job of reusing code. Design patterns have been the focus of many debates, "should we use design patterns?" "At the beginning of this article, I also try to avoid" too tangled up in this problem ", I think, the design pattern has its existence value, at least in the specific project, indeed in many version iterations save the workload, improve efficiency, but if in a small project in order to" show I will design patterns "and use design patterns, it is unreasonable.
"Seven-day self-made PHP framework" third Day: PHP implementation design pattern