PHP十二种设计模式_PHP教程
PHP十二种设计模式
PSR-0规范的设计基础1.全部使用命名空间
2.所有php文件必须自动载入,不能有include/require
spl_autoload_register
3.单一入口模式
1.三种基本的设计模式
工厂模式
用一个工厂方法去替换掉一个new
class Factory{
static function createDatabase(){
$db = new Database;
return $db;
}
}
使用的时候就可以用 $db = Factory::createDatabase();
单例模式
class Database{
private $db;
private function __construct(){
//这里可以写连接数据库
}
static function getInstance(){
if(self::$db){
return self::$db;
}else{
self::$db=new self()
return self::$db;//private可以自身调用
}
}
function where(){
}
}
如果是工厂加单例模式
class Factory{
static function createDatabase(){
$db = Database::getInstance();
return $db;
}
}
注册器(树)模式
class Register{
protected static $object;
static function set($alias,$object){
self::$object[$alias]=$object;
}
static function get($name)
{
return self::$object[$name];
}
function _unset($alias){
unset(self::$object[$alias]);
}
}
跟工厂方法结合
class Factory{
static function createDatabase(){
$db = Database::getInstance();
Register::set('db1',$db);
return $db;
}
}
索引直接调用
$db = Register::get('db1');
适配器模式
1.适配器模式,可以将截然不同的函数接口封装成统一的API
2.实际应用举例,PHP的数据库操作有mysql,mysqli,pdo3种,可以用适配器模式
统一成一致,类似的场景还有cache适配器,将memcache,redis,file,apc等不同的缓存函数,统一成一致,
比如说有一个Database.php里面有一个接口
interface IDatabase
{
function connect($host,$user,$pwd,$dbname);
function query($sql);
function close();
}
再下面有三个类
class mysql implements IDatabase{
private $con;
function connect($host,$user,$pwd,$dbname){
$this->con = mysql_connect($host,$user,$pwd);
mysql_select_db($dbname,$this->con);
}
function query($sql){
return mysql_query($sql,$this->con);
}
function close(){
return mysql_close($this->con);
}
}
class mysqli implements IDatabase{
protected $con;
function connect($host,$user,$pwd,$dbname)
{
$this->con = mysqli_connect($host,$user,$pwd,$dbname);
}
function query($sql)
{
return mysqli_query($this->con,$sql);
}
function close()
{
return mysqli_close($this->con);
}
}
class PDO implements IDatabase{
protected $con;
function connect($host,$user,$pwd.$dbname)
{
$con = new \PDO("mysql:host=$host;dbname=$dbname",$user,$pwd);
$this->con=$con;
}
function query($sql){
return $this->con->query($sql);
}
function close(){
unset($this->con);
}
}
这样我们调用的时候
$db = new mysql();或new mysqli();或new PDO();
$db->connect('127.0.0.1','root','root');
$db->query();
$db->close();
策略模式
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式
实际应用距离,假如一个电商系统的网站系统,针对男性女性用户要各自跳转到不同的商品类别
首先声明一个策略的接口文件
interface UserStrategy{
function showAd();
function showcategory();
}
//第一个策略 针对女性用户
class femaleUserStrategy implements UserStrategy{
function showAd(){
echo '2014新款女装';
}
function showCategory()
{
echo '女装';
}
}
//第二个策略,针对于男性用户
class maleUserStrategy implements UserStrategy{
function showAd(){
echo '2014新款男装';
}
function showCategory()
{
echo '男装';
}
}
//如果有一个page类
class page{
protected $strategy;
function index(){
$this->strategy->showAd();
$this->strategy->showCategory();
}
function setStrategy(\UserStrategt $strategy){
$this->strategy=$strategy;
}
}
$page = new Page();
if(isset($_GET['female'])){
$strategy = new femaleUserStrategy();
}else{
$strategy = new maleUserStrategy();
}
$page->setStrategy($strategy);
$page->index();
从一个硬编码到解耦的模式
数据对象映射模式
数据对象映射模式,是将对象和数据存储映射起来,对一个
对象的操作会映射为对数据存储的操作。
在代码中实现数据对象映射模式,我们将实现一个ORM类,将复杂的sql语句映射成对象属性的操作
class User{
public $id;
public $name;
public $mobile;
public $regtime;
protected $db;
function __construct($id){
//先取数据
$this->db = new mysql();
$this->db->connect('xxxxx'xxxx);
$res = $this->db->query('select * from XXX where id = {$id}');
$data = $res->fetch_assoc();
$this->id=$data['id'];
$this->name=$data['name'];
$this->mobile=$data['mobile'];
$this->regtime=$data['regtime'];
return $res;
}
function __destruct(){
//可以作为修改使用
$this->db->query('update xx set name={$this->name} mobile={$this->mobile}XXXXX where id = {$this->id}');
}
}
$user = new User(1);//1对应数据库中id为一
$user->mobile = '155555555';
$user->name='test';
$user->regtime=time();
//在这里没有sql语句.只有对对象的操作
综合运用(工厂模式,注册器模式,适配器模式)
与
观察者模式
1.观察者模式,当一个对象状态发生改变时,依赖他的对象全部会收到通知,并自动更新。
2.场景:一个事件发生后,要执行一连串更新操作,传统的编程方式,就
是在事件的代码之后直接加入处理逻辑,当更新的逻辑增多之后,代码会变得难以维护,这种方式是耦合的,侵入式的,
增加心的逻辑需要修改事件主体的代码
3.观察者模式实现了低耦合,非侵入式的通知更新机制。
demo
class Event{
function trigger(){
echo "Event";//表示事件发生了
//开始写更新逻辑了
echo '逻辑1';
echo '逻辑2';
echo '逻辑3';
}
}
$event = new Event();//传统的方式是耦合的,侵入式的,
//必须要改源码,所以我们定义一个观察者模式
demo
//在来一个接口
//先来一个基类抽象类
abstract class EventGenerator{
private $observers = array();
function addObserver(Observer$observer){
$this->obervers[]=$oberver;
}
function notify(){
foreach($this->obervers as $observer)
{
$observer->updata();
}
}
}
interface Oberver{
function update($event_info = null);
}
//所以说这个时候我们需要Event类继承这个基类
class Event extends EventGenerator{
function trigger(){
echo "Event";//表示事件发生了
$this->notify();
}
}
class Observer1 implements Observer{
function updata($event_info=null)
{
echo "逻辑一";
}
}
class Oberver2 implements Oberver{
function updata($event_info=null)
{
echo "逻辑二";
}
}
原型模式
1.与工厂模式作用类似,都是用来创建对象
2.与工厂模式的实现不同,原型模式先创建好一个原型
对象,然后通过clone原型对象来创建新的对象,这样就免去了类
创建时重复的初始化操作
3.原型模式适合于大对象的创建,创建一个大对象需要很大的开销,如果每次new就会消耗很大,
原型模式仅仅拷贝内存即可。
假如有一个画布类。new很复杂
我又想使用他两次
这样我们就可以用原型模式解决new的问题,用clone替代new
初始化之后直接clone即可。
装饰器模式
1.装饰器模式,可以动态的添加修改类的功能。
2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的
编程模式,需要写一个子类继承他,并重新实现类的方法。
3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
如果我们有一个画布类。只能打印一个正方形,假如我们想要添加一个颜色
一般是写一个子类,继承那个画布类。
重写产生画布的方法。那我们如果要增加很多功能呢?
是不是要重写很多类?
下面我们用装饰器模式解决这个问题
首先我们先声明一个画布的装饰器的接口
interface DrawDecorator{
function beforeDraw();
function afterDraw();
}
比如我们要修改画布类的draw()方法
所以我们在draw()方法中调用
function draw(){
$this->beforeDraw();
//这里是原来代码的内容
$this->afterDraw();
}
再在画布类中添加一个protected $decorators[]=array();
在添加一个方法,用来接收装饰器接口
function addDecorator(DrawDecorator $decorator){
$this->decorators[]=$decorator;
}
再添加两个调用装饰器的方法
function beforeDraw(){
foreach($this->decorators as $decorator)
{
$decorator->beforeDraw();
}
}
function afterDraw(){
//进行反转,后进先出
$decorators = array_reverse($this->decorators);
foreach($decorators as $decorator)
{
$decorator->afterDraw();
}
}
我们有一个颜色装饰器
class ColorDrawDecorator implements DrawDecorator{
protected $color;
function __construct($color='red')
{
$this->color= $color;
}
function beforDraw()
{
echo "
}
function afterDraw()
{
echo "
}
}
在这里就不用去继承去实现了
$a = new canvas();//实例化画布类
$a -> init();//初始化
$a -> addDecorator(new colorDrawDecorator('green'));//添加一个颜色的装饰器类
迭代器模式
1.迭代器模式,在不需要了解内部实现的前提下,遍历yige
聚合对象的内部元素
2.相比传统的编程模式,迭代器模式可以隐藏遍历元素的所需的操作
比如遍历一个数据库,然后拿到所有对象
class Alluser implements Iterator{
protected $ids;
protected $index;//迭代器当前位置
protected $data=array();
//Iterator为迭代器接口
fucntion __construct(){
$db = Factory::getDatabase();
$result = $db->query("selecy id from user");
$this->ids = $db->mysql_fetch_assoc($result);
}
function current(){
//获取当前元素
$id=$this->ids[$this->index]['id'];
return Factory::getUser($id);
}
function next(){
//下一个元素
$this->index ++;
}
function valid()
{
//判断是否有数据
return $this->index ids);
}
function rewind(){
$this->index=0;//第一步到开头
}
function key(){
//获取当前索引
return $this->index;
}
}
$users = new Alluser();
foreach ($users as $user)
{
var_dump($user);
}
代理模式
1.在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象,隐藏实体具体实现细节。
就是写一个
面向对象编程的基本原则
1.单一职责:一个类,只需要做好一件事情
2.开放封闭:一个类,应该是可扩展的,而不可修改的
3.依赖倒置:一个类,不应该强依赖另外一个类,每个类对于另外一个类都是可替换的
4.配置化:尽可能的使用配置,而不是硬编码。
5.面向接口编程:只需要关心接口,不需要关心实现。
MVC架构原理
我们先new 一个Config的对象
$config = new Config(__DIR__.'/configs');
$config['controller'];
那么有一个Config类
class Config implements \ArrayAccess{
//ArrayAccess接口是内置的接口,表示允许数组传值,其中有要实现四个方法
protected $path;
protected $configs=array();
function __construct($path)
{
$this->path=$path;
}
function offsetGet($key){
//获取该配置数组文件名key
if(empty($this->configs[$key]))
//如果原配置文件中不存在该数组文件名,那么就去加载
{
$file_path=$this->path.'/'.$key.'.php';//生成加载路径
$config = require $file_path;
$this->config[$key]=$config;
}
return $this->configs[$key];
}
function offsetSet($key,$value)
{
//设置数组的key
}
function offsetExists($key)
{ //检测数组的key是否存在
return isset($this->configs[$key]);
}
function offsetUnset($key)
{ //删除数组的key
}
}
配置文件比如controller.php
$config = array(
'home'=>array(
'decorator'=>array(
'IMooc\Dectorator\Template',
),
),
);
配置与设计模式
1.PHP中使用ArrayAccess实现配置文件的加载
2.在工厂方法中读取配置,生成可配置化的对象
3.使用装饰器模式实现权限验证,模板渲染,json串化
4.使用观察者模式实现数据更新事件的一系列更新操作
5.使用代理模式实现数据库的主从自动切换

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java 프레임워크에서 디자인 패턴과 아키텍처 패턴의 차이점은 디자인 패턴이 클래스와 객체(예: 팩토리 패턴) 간의 상호 작용에 중점을 두고 소프트웨어 디자인의 일반적인 문제에 대한 추상적인 솔루션을 정의한다는 것입니다. 아키텍처 패턴은 계층화된 아키텍처와 같은 시스템 구성 요소의 구성 및 상호 작용에 중점을 두고 시스템 구조와 모듈 간의 관계를 정의합니다.

어댑터 패턴은 호환되지 않는 개체가 함께 작동할 수 있도록 하는 구조적 디자인 패턴입니다. 이는 개체가 원활하게 상호 작용할 수 있도록 하나의 인터페이스를 다른 인터페이스로 변환합니다. 개체 어댑터는 적응된 개체를 포함하는 어댑터 개체를 만들고 대상 인터페이스를 구현하여 어댑터 패턴을 구현합니다. 실제적인 경우 클라이언트(예: MediaPlayer)는 어댑터 모드를 통해 고급 형식 미디어(예: VLC)를 재생할 수 있지만 클라이언트 자체는 일반 미디어 형식(예: MP3)만 지원합니다.

데코레이터 패턴은 원래 클래스를 수정하지 않고도 객체 기능을 동적으로 추가할 수 있는 구조적 디자인 패턴입니다. 추상 컴포넌트, 콘크리트 컴포넌트, 추상 데코레이터, 콘크리트 데코레이터의 협업을 통해 구현되며, 변화하는 요구에 맞게 클래스 기능을 유연하게 확장할 수 있습니다. 이 예에서는 우유와 모카 데코레이터가 총 $2.29의 가격으로 Espresso에 추가되어 객체의 동작을 동적으로 수정하는 데코레이터 패턴의 힘을 보여줍니다.

1. 팩토리 패턴: 객체 생성과 비즈니스 로직을 분리하고, 팩토리 클래스를 통해 지정된 형태의 객체를 생성합니다. 2. 관찰자 패턴: 주체 개체가 관찰자 개체에 상태 변경을 알리도록 허용하여 느슨한 결합 및 관찰자 패턴을 달성합니다.

디자인 패턴은 재사용 및 확장 가능한 솔루션을 제공하여 코드 유지 관리 문제를 해결합니다. 관찰자 패턴: 개체가 이벤트를 구독하고 이벤트가 발생할 때 알림을 받을 수 있도록 합니다. 팩토리 패턴: 구체적인 클래스에 의존하지 않고 객체를 생성하는 중앙 집중식 방법을 제공합니다. 싱글톤 패턴: 클래스에 전역적으로 액세스 가능한 개체를 만드는 데 사용되는 인스턴스가 하나만 있는지 확인합니다.

Java 프레임워크에서 디자인 패턴을 사용하면 향상된 코드 가독성, 유지 관리성 및 확장성이 향상된다는 이점이 있습니다. 단점으로는 복잡성, 성능 오버헤드, 과도한 사용으로 인한 가파른 학습 곡선 등이 있습니다. 실제 사례: 프록시 모드는 개체를 지연 로드하는 데 사용됩니다. 디자인 패턴을 현명하게 사용하여 장점을 활용하고 단점을 최소화하세요.

TDD는 고품질 PHP 코드를 작성하는 데 사용됩니다. 단계에는 테스트 사례 작성, 예상 기능 설명 및 실패 만들기가 포함됩니다. 과도한 최적화나 세부 설계 없이 테스트 케이스만 통과하도록 코드를 작성합니다. 테스트 케이스를 통과한 후 코드를 최적화하고 리팩터링하여 가독성, 유지 관리성 및 확장성을 향상시킵니다.

Guice 프레임워크는 다음을 포함한 다양한 디자인 패턴을 적용합니다. 싱글톤 패턴: @Singleton 주석을 통해 클래스에 인스턴스가 하나만 있는지 확인합니다. 팩토리 메소드 패턴: @Provides 주석을 통해 팩토리 메소드를 생성하고 종속성 주입 중에 객체 인스턴스를 얻습니다. 전략 모드: 알고리즘을 다양한 전략 클래스로 캡슐화하고 @Named 주석을 통해 특정 전략을 지정합니다.
