原文请见:
http://www.ucai.cn/blogdetail/7020?mid=1&f=12
可以在线运行查看效果哦!
我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。
一、设计模式简介
首先我们来认识一下什么是设计模式:
设计模式是一套被反复使用、容易被他人理解的、可靠的代码设计经验的总结。
设计模式不是Java的专利,我们用面向对象的方法在PHP里也能很好的使用23种设计模式。
那么我们常说的架构、框架和设计模式有什么关系呢?
架构是一套体系结构,是项目的整体解决方案;框架是可供复用的半成品软件,是具体程序代码。架构一般会涉及到采用什么样的框架来加速和优化某部分问题的解决,而好的框架代码里合理使用了很多设计模式。
二、提炼设计模式的几个原则:
开闭原则:模块应对扩展开放,而对修改关闭。
里氏代换原则:如果调用的是父类的话,那么换成子类也完全可以运行。
依赖倒转原则:抽象不依赖细节,面向接口编程,传递参数尽量引用层次高的类。
接口隔离原则:每一个接口只负责一种角色。
合成/聚合复用原则:要尽量使用合成/聚合,不要滥用继承。
三、设计模式的功用?
1、设计模式能解决
替换杂乱无章的代码,形成良好的代码风格
代码易读,工程师们都能很容易理解
增加新功能时不用修改接口,可扩展性强
稳定性好,一般不会出现未知的问题
2、 设计模式不能解决:
设计模式是用来组织你的代码的模板,而不是直接调用的库;
设计模式并非最高效,但是代码的可读性和可维护性更重要;
不要一味追求并套用设计模式,重构时多考虑;
四、设计模式分类
1、创建型模式:
单例模式、工厂模式(简单工厂、工厂方法、抽象工厂)、创建者模式、原型模式。
2、结构型模式:
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
3、行为型模式:
模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。
五、创建型设计模式
1、单例模式
目的:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
应用场景:数据库连接、缓存操作、分布式存储。
<?php /** * 优才网公开课示例代码 * * 单例模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ class DbConn { private static $_instance = null; protected static $_counter = 0; protected $_db; //私有化构造函数,不允许外部创建实例 private function __construct() { self::$_counter += 1; } public function getInstance() { if (self::$_instance == null) { self::$_instance = new DbConn(); } return self::$_instance; } public function connect() { echo "connected: ".(self::$_counter)."\n"; return $this->_db; } } /* * 不使用单例模式时,删除构造函数的private后再测试,第二次调用构造函数后,_counter变成2 */ // $conn = new DbConn(); // $conn->connect(); // $conn = new DbConn(); // $conn->connect(); //使用单例模式后不能直接new对象,必须调用getInstance获取 $conn = DbConn::getInstance(); $db = $conn->connect(); //第二次调用是同一个实例,_counter还是1 $conn = DbConn::getInstance(); $db = $conn->connect(); ?>
特别说明:这里getInstance里有if判断然后再生成对象,在多线程语言里是会有并发问题的。例如java的解决方案有二个,给方法加上synchronized关键词变成同步,或者把_instanc的初始化提前放到类成员变量定义时,但是这2种方式php都不支持。不过因为php不支持多线程所以不需要考虑这个问题了。
2、工厂模式
实现:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
应用场景:众多子类并且会扩充、创建方法比较复杂。
<?php /** * 优才网公开课示例代码 * * 工厂模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //抽象产品 interface Person { public function getName(); } //具体产品实现 class Teacher implements Person { function getName() { return "老师\n"; } } class Student implements Person { function getName() { return "学生\n"; } } //简单工厂 class SimpleFactory { public static function getPerson($type) { $person = null; if ($type == 'teacher') { $person = new Teacher(); } elseif ($type == 'student') { $person = new Student(); } return $person; } } //简单工厂调用 class SimpleClient { function main() { // 如果不用工厂模式,则需要提前指定具体类 // $person = new Teacher(); // echo $person->getName(); // $person = new Student(); // echo $person->getName(); // 用工厂模式,则不需要知道对象由什么类产生,交给工厂去决定 $person = SimpleFactory::getPerson('teacher'); echo $person->getName(); $person = SimpleFactory::getPerson('student'); echo $person->getName(); } } //工厂方法 interface CommFactory { public function getPerson(); } //具体工厂实现 class StudentFactory implements CommFactory { function getPerson(){ return new Student(); } } class TeacherFactory implements CommFactory { function getPerson() { return new Teacher(); } } //工厂方法调用 class CommClient { static function main() { $factory = new TeacherFactory(); echo $factory->getPerson()->getName(); $factory = new StudentFactory(); echo $factory->getPerson()->getName(); } } //抽象工厂模式另一条产品线 interface Grade { function getYear(); } //另一条产品线的具体产品 class Grade1 implements Grade { public function getYear() { return '2003级'; } } class Grade2 implements Grade { public function getYear() { return '2004级'; } } //抽象工厂 interface AbstractFactory { function getPerson(); function getGrade(); } //具体工厂可以产生每个产品线的产品 class Grade1TeacherFactory implements AbstractFactory { public function getPerson() { return new Teacher(); } public function getGrade() { return new Grade1(); } } class Grade1StudentFactory implements AbstractFactory { public function getPerson() { return new Student(); } public function getGrade() { return new Grade1(); } } class Grade2TeacherFactory implements AbstractFactory { public function getPerson() { return new Teacher(); } public function getGrade() { return new Grade2(); } } //抽象工厂调用 class FactoryClient { function printInfo($factory) { echo $factory->getGrade()->getYear().$factory->getPerson()->getName(); } function main() { $client = new FactoryClient(); $factory = new Grade1TeacherFactory(); $client->printInfo($factory); $factory = new Grade1StudentFactory(); $client->printInfo($factory); $factory = new Grade2TeacherFactory(); $client->printInfo($factory); } } //简单工厂 //SimpleClient::main(); //工厂方法 //CommClient::main(); //抽象工厂 FactoryClient::main(); ?>
三种工厂的区别是,抽象工厂由多条产品线,而工厂方法只有一条产品线,是抽象工厂的简化。而工厂方法和简单工厂相对,大家初看起来好像工厂方法增加了许多代码但是实现的功能和简单工厂一样。但本质是,简单工厂并未严格遵循设计模式的开闭原则,当需要增加新产品时也需要修改工厂代码。但是工厂方法则严格遵守开闭原则,模式只负责抽象工厂接口,具体工厂交给客户去扩展。在分工时,核心工程师负责抽象工厂和抽象产品的定义,业务工程师负责具体工厂和具体产品的实现。只要抽象层设计的好,框架就是非常稳定的。
3、创建者模式
在创建者模式中,客户端不再负责对象的创建与组装,而是把这个对象创建的责任交给其具体的创建者类,把组装的责任交给组装类,客户端支付对对象的调用,从而明确了各个类的职责。
应用场景:创建非常复杂,分步骤组装起来。
<?php /** * 优才网公开课示例代码 * * 创建者模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //购物车 class ShoppingCart { //选中的商品 private $_goods = array(); //使用的优惠券 private $_tickets = array(); public function addGoods($goods) { $this->_goods[] = $goods; } public function addTicket($ticket) { $this->_tickets[] = $ticket; } public function printInfo() { printf("goods:%s, tickets:%s\n", implode(',', $this->_goods), implode(',', $this->_tickets)); } } //假如我们要还原购物车的东西,比如用户关闭浏览器后再打开时会根据cookie还原 $data = array( 'goods' => array('衣服', '鞋子'), 'tickets' => array('减10'), ); //如果不使用创建者模式,则需要业务类里一步步还原购物车 // $cart = new ShoppingCart(); // foreach ($data['goods'] as $goods) { // $cart->addGoods($goods); // } // foreach ($data['tickets'] as $ticket) { // $cart->addTicket($ticket); // } // $cart->printInfo(); // exit; //我们提供创建者类来封装购物车的数据组装 class CardBuilder { private $_card; function __construct($card) { $this->_card = $card; } function build($data) { foreach ($data['goods'] as $goods) { $this->_card->addGoods($goods); } foreach ($data['tickets'] as $ticket) { $this->_card->addTicket($ticket); } } function getCrad() { return $this->_card; } } $cart = new ShoppingCart(); $builder = new CardBuilder($cart); $builder->build($data); echo "after builder:\n"; $cart->printInfo(); ?>
可以看出,使用创建者模式对内部数据复杂的对象封装数据组装过程后,对外接口就会非常简单和规范,增加修改新数据项也不会对外部造成任何影响。
3、 原型模式
用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
应用场景: 类的资源非常多、性能和安全要求,一般和工厂方法结合使用。
<?php /** * 优才网公开课示例代码 * * 原型模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //声明一个克隆自身的接口 interface Prototype { function copy(); } //产品要实现克隆自身的操作 class Student implements Prototype { //简单起见,这里没有使用get set public $school; public $major; public $name; public function __construct($school, $major, $name) { $this->school = $school; $this->major = $major; $this->name = $name; } public function printInfo() { printf("%s,%s,%s\n", $this->school, $this->major, $this->name); } public function copy() { return clone $this; } } $stu1 = new Student('清华大学', '计算机', '张三'); $stu1->printInfo(); $stu2 = $stu1->copy(); $stu2->name = '李四'; $stu2->printInfo(); ?>
这里可以看到,如果类的成员变量非常多,如果由外部创建多个新对象再一个个赋值,则效率不高代码冗余也容易出错,通过原型拷贝复制自身再进行微小修改就是另一个新对象了。
设计模式的第一部分,创建型模式就总结完了。下面还有两部分结构型设计模式和行为型设计模式稍后继续。
公开课链接:http://www.ucai.cn/train?f=12
相关推荐
简单工厂模式是软件设计模式中的一种,它属于创建型模式,主要用来解决对象的创建问题。在PHP中,我们可以利用这种模式来简化对象的实例化过程,减少代码的耦合度,提高代码的可维护性。 简单工厂模式的核心思想是...
2. PHP设计模式的类型:PHP中常用的设计模式可以分为三大类,分别是创建型模式、结构型模式和行为型模式。创建型模式主要涉及对象实例化的过程,如单例模式、工厂模式、建造者模式等;结构型模式涉及如何组合类和...
2. **工厂模式**:工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在PHP中,工厂模式可以用来抽象产品创建过程,使得更换或扩展产品变得更加容易。 3. **抽象工厂模式**:这是一种更高级别的工厂...
《Learning PHP设计模式》这本书为PHP开发者提供了一个深入理解并应用设计模式的宝贵资源。 该书中文翻译版于2014年首次在中国出版,由电力出版社发行,以清晰的PDF格式呈现,便于读者阅读和查阅。目录结构完整,...
1. 创建型模式:包括单例模式(Singleton)、工厂模式(Factory)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式(Prototype)。这些模式主要关注对象的创建过程,使得创建过程更加灵活,...
《PHP设计模式》是一本探讨如何在PHP编程中应用设计模式的书籍。设计模式是软件工程领域中,解决常见问题的模板或策略。本书作者是美国的Aaron Saray,内容详尽地介绍了各种设计模式,旨在帮助PHP开发者构建出更加...
1. 工厂模式:这是一种创建型模式,用于抽象实例化过程,使得创建对象时无需指定具体类,提高了代码的灵活性。 2. 单例模式:确保一个类只有一个实例,并提供全局访问点,常用于管理资源或控制类的实例化。 3. ...
1. 创建型模式: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。 - 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的...
1. **创建型模式**: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:提供一个接口来创建相关或依赖对象的家族,而无需指定具体类。 - 抽象工厂模式:提供一个创建一系列相关或相互...
根据提供的文件信息,本文将对《Learning_PHP设计模式》这一主题进行深入解析,重点围绕PHP设计模式的基础概念、分类及应用场景展开讨论。 ### PHP设计模式基础 #### 1. 设计模式简介 设计模式是在软件工程领域内...
《PHP设计模式》一书由美国作者Aaron Saray撰写,主要针对PHP开发者,详细阐述了在实际编程过程中如何运用设计模式提升代码质量和可维护性。设计模式是软件工程中的最佳实践,它们是解决常见问题的经验总结,使得...
PHP设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。 1. **创建型模式**: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:提供一个接口来创建对象,但让子类决定实例化...
以下是根据标题“php设计模式案例汇总.zip”和描述中提到的九种创建型设计模式的详细解释: 1. 抽象工厂模式:它提供了一种创建相关或相互依赖对象的接口,而无需指定它们的具体类。在PHP中,抽象工厂常用于数据库...
1. 创建型模式:这类模式主要关注对象的创建过程,包括单例(Singleton)、工厂方法(Factory Method)、抽象工厂(Abstract Factory)、建造者(Builder)和原型(Prototype)。例如,PHP中可以通过static关键字...
本资料“PHP设计模式介绍”是一个CHM文档,提供了对设计模式的深入理解和应用实例。 设计模式分为三大类:创建型模式、结构型模式和行为型模式。每种模式都针对软件设计中的特定问题,提供了最佳实践的解决方案。 ...
适配器模式是一种结构型设计模式,它的主要目的是使不兼容的接口能够协同工作。在实际开发中,我们可能会遇到这样的情况:一个类库或者服务提供了一个接口,而我们的代码需要使用另一个接口。适配器模式就充当了两者...
1. **创建型模式**: - **单例模式(Singleton)**:保证一个类只有一个实例,并提供一个全局访问点。 - **工厂模式(Factory)**:提供一个接口用于创建相关或依赖对象的家族,而无需指定它们的具体类。 - **...
工厂模式是创建型设计模式,它提供了一种创建对象的最佳方式。根据输入参数或应用程序配置,工厂模式可以动态地返回其他类的实例。这有助于减少代码的耦合,增加系统的可扩展性。 以下是一个基本的工厂模式示例,...
设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。 创建型模式提供了创建对象的机制,同时又避免了暴露创建逻辑,并且提供了一种将创建逻辑和使用逻辑分离的清晰方式。例如: - 工厂模式(Factory ...