原文请见
http://www.ucai.cn/blogdetail/7020?action=gt&mid=1
可以在线运行查看效果哦!
上一篇我们介绍了设计模式的特性并且详细讲解了4种创建型模式,创建型模式是负责如何产生对象实例的,现在我们继续来给大家介绍结构型模式。
一、什么是结构型模式?
结构型模式是解析类和对象的内部结构和外部组合,通过优化程序结构解决模块之间的耦合问题。
二、结构型模式的种类:
- 适配器模式
- 桥接模式
- 装饰模式
- 组合模式
- 外观模式
- 享元模式
- 代理模式
1、 适配器模式(Adapter)
将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。
应用场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。
代码实现
<?php /** * 优才网公开课示例代码 * * 适配器模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //老的代码 class User { private $name; function __construct($name) { $this->name = $name; } public function getName() { return$this->name; } } //新代码,开放平台标准接口 interfaceUserInterface { function getUserName(); } class UserInfoimplements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return$this->user->getName(); } } $olduser = newUser('张三'); echo$olduser->getName()."\n"; $newuser = newUserInfo($olduser); echo$newuser->getUserName()."\n"; ?>
注意点:这里的新接口使用了组合方式,UserInfo内部有一个成员变量保存老接口User对象,模块之间是松耦合的,这种结构其实就是组合模式。不要使用继承,虽然UserInfo继承User也能达到同样的目的,但是耦合度高,相互产生影响。
2、 桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立变化
特点:独立存在,扩展性强
应用:需要不断更换调用对象却执行相同的调用方法,实现扩展功能
代码实现
<?php /** * 优才网公开课示例代码 * * 桥接模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ abstract classPerson { abstract function getJob(); } class Studentextends Person { public function getJob() { return '学生'; } } class Teacherextends Person { public function getJob() { return '老师'; } } class BridgeObj { protected $_person; public function setPerson($person) { $this->_person = $person; } public function getJob() { return$this->_person->getJob(); } } $obj = newBridgeObj(); $obj->setPerson(newStudent()); printf("本次桥接对象:%s\n", $obj->getJob()); $obj->setPerson(newTeacher()); printf("本次桥接对象:%s\n", $obj->getJob()); ?>
3、 装饰模式
动态地给一个对象添加额外的职责。在原有的基础上进行功能增强。
特点:用来增强原有对象功能,依附于原有对象。
应用:用于需要对原有对象增加功能而不是完全覆盖的时候
代码实现
<?php /** * 优才网公开课示例代码 * * 装饰模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //产品 abstract classPerson { abstract function getPermission(); } //被装饰者 class User extendsPerson { public function getPermission() { return '公开文档'; } } //装饰类 class PermUserextends Person { protected $_user; protected $_special = ''; function __construct($user) { $this->_user = $user; } public function getPermission() { return$this->_user->getPermission() . $this->_special; } } //装饰类产品 class JavaUserextends PermUser { protected $_special = ' java程序'; } class CPlusUserextends PermUser { protected $_special = ' c++程序'; } $user = new User(); printf("permission:%s\n", $user->getPermission()); $user = newJavaUser($user); printf("permission:%s\n", $user->getPermission()); $user = newCPlusUser($user); printf("permission:%s\n", $user->getPermission()); ?>
大家想想装饰和继承的区别在哪?
如果是上面的例子,如果用继承,是CPlusUser继承JavaUser还是反过来呢?谁也不知道最终使用者需要哪一种。
在多层关系的情况下,装饰是和顺序无关并且随时增加装饰,而继承只能是特定的顺序,所以装饰模式会更加的灵活。
4、组合模式
将对象组合成树形结构表示“部分-整体”的层次结构。
特点:灵活性强
应用:对象的部分-整体的层次结构,模糊组合对象和简单对象处理问题
代码实现
<?php /** * 优才网公开课示例代码 * * 组合模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //继承模式 class UserBaseInfo { private $name; function __construct($name) { $this->name = $name; } public function getName() { return$this->name; } } class User extendsUserBaseInfo { private $login = false; public function setLogin($islogin) { $this->login= $islogin; } public function isLogin() { return$this->login; } } $user = new User('张三'); $user->setLogin(true); if($user->isLogin()) { echo $user->getName()."已经登录了\n"; } else { echo $user->getName()."还没有登录\n"; } //组合模式 class LoginInfo { protected $user; protected $login = false; public function setLogin($user, $isLogin){ $this->user = $user; $this->login = $isLogin; } public function isLogin() { return $this->login; } } $user = new User('张三'); $login = newLoginInfo(); $login->setLogin($user,true); if($login->isLogin()) { echo $user->getName()."已经登录了\n"; } else { echo $user->getName()."还没有登录\n"; } //部分可以更换,用继承则不行 class Admin { protected $level; function __construct($level) { $this->level = $level; } function getLevel() { return $this->level; } } $admin = newAdmin(1); $login->setLogin($admin,true); if($login->isLogin()) { printf("级别为 %d 的管理员已经登录了\n",$admin->getLevel()); } else { printf("级别为 %d 的管理员还没有登录\n",$admin->getLevel()); } ?>
上面的例子分别展示了使用继承和组合来处理新功能,在简单的情况下看似区别不大,但在项目后期越来越复杂的时候组合模式的优势就越来越明显了。
例如上面的登录信息,如果要增加登录次数、最后登录时间、登录ip等信息,登录本身就会变成一个比较复杂的对象。如果以后有新的需求比如好友信息、用户的访问信息等,再要继承的话,用户类就会变得非常庞大,难免各父类之间没有冲突的变量和方法,而外部访问用户类的众多方法也变得很费劲。采用组合模式后,一个类负责一个角色,功能区分非常明显,扩展方便。
5、 外观模式(门面模式)
为了系统中的一组接口提供一个一致的界面
特点:向上抽取,有共性
应用:内部接口众多,由统一的接口来调用
代码实现
<?php /** * 优才网公开课示例代码 * * 外观模式,也叫门面模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ class Operation { public function testPlus() { printf("plus: %s\n", (1+ 2 == 3 ? 'true' : 'false')); } public function testMinus() { printf("minus: %s\n", (3- 2 == 2 ? 'true' : 'false')); } public function testTimes() { printf("times: %s\n", (2* 3 == 6 ? 'true' : 'false')); } } class Tester { protected $_operation; function __construct() { $this->_operation = newOperation(); } public function testAll() { $this->_operation->testPlus(); $this->_operation->testMinus(); $this->_operation->testTimes(); } } //测试用例,测试全部接口 $tester = newTester(); $tester->testAll(); ?>
门面模式估计大家在实际代码中都已经使用到了,接口较多时把相似功能的接口封装成一个接口供外部调用,这就是门面模式。
6、 享元模式
运用共享技术有效地支持大量细粒度对象,采用一个共享来避免大量有相同内容对象的开销。这种开销中最直观的就是内存的损耗。
特点:高效性,共享性
应用:系统底层的设计。例如字符串的创建。如果两个字符串相同,则不会创建第二个字符串,而是第二个的引用直接指向第一个字符串。$str1=”abc”,$str2=”abc”.则内存存储中只会创建一个字符串“abc”而引用$str1.$str2都会指向它。
7、 代理模式
为其他对象提供一个代理来控制对这个对象的访问,就是给某一对象提供代理对象,并由代理对象控制具体对象的引用。能够协调调用者和被调用者,能够在一定程度上降低系统的耦合性。
特点:低耦合性,独立性好,安全性
应用:客户访问不到或者被访问者希望隐藏自己,所以通过代理来访问自己。
代码实现
<?php /** * 优才网公开课示例代码 * * 代理模式 * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ //内部对象 class User { public function getName() { return '张三'; } public function getType() { return '付费用户'; } } //代理接口定义,例如开放平台 interfaceUserInterface { function getName(); } //代理对象 class UserProxyimplements UserInterface { protected $_user; function __construct() { $this->_user = new User(); } public function getName() { return$this->_user->getName(); } } //内部调用 $user = new User(); printf("username:%s\n", $user->getName()); printf("usertype:%s\n", $user->getType()); //外部调用 // $user = newUserProxy(); // printf("username:%s\n", $user->getName()); // printf("usertype:%s\n", $user->getType());//不能访问,及时知道内部对象有这个方法 ?>
三、总结
1、代理模式、适配器模式、门面模式、装饰模式的区别
a、 相同之处:都封装一个内部对象,调用内部对象的方法
b、 不同之处:各自有各自的特性和应用场景,不能相互替代。所以用的时候要仔细分析用那种合适。
2、 关于模式的选用问题
模式的选用要根据实际的业务需求,通过对业务逻辑的仔细分析,再根据模式具有的特性和应用场景进行合理的选择和区分。大部分情况下业务的场景决定了哪种模式,而不是选择哪个模式去实现一个业务,少数情况几种模式确实都能解决问题,那主要就是考虑以后的扩展了。
到这里我们已经了解了7种结构型模式,下一篇我们继续给大家介绍设计模式的行为型模式,先预览一下行为型模式的种类吧:
1、模版方法模式
2、命令模式
3、迭代器模式
4、观察者模式
5、终结者模式
6、备忘录模式
7、解释器模式
8、状态模式
9、策略模式
10、职责链模式
11、访问者模式
相关推荐
2. PHP设计模式的类型:PHP中常用的设计模式可以分为三大类,分别是创建型模式、结构型模式和行为型模式。创建型模式主要涉及对象实例化的过程,如单例模式、工厂模式、建造者模式等;结构型模式涉及如何组合类和...
常见的结构型模式包括适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、装饰者模式(Decorator)、外观模式(Facade)、享元模式(Flyweight)和代理模式(Proxy)。 行为型模式关注对象之间的...
2. 结构型模式:如代理模式(Proxy)、装饰器模式(Decorator)、适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、外观模式(Facade)和享元模式(Flyweight)。这些模式关注如何组织类和对象,...
**PHP设计模式详解** 在IT领域,设计模式是一种在特定情境下解决常见问题的标准方法,它们代表了软件设计中的最佳实践。PHP作为一种广泛使用的服务器端脚本语言,同样可以从设计模式中受益。《Learning PHP设计模式...
2. 结构型模式: - 代理模式:为其他对象提供一种代理以控制对这个对象的访问。 - 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。 - 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次...
《Learning PHP设计模式》这本书是面向PHP开发者的一本专业指南,旨在帮助读者深入理解并掌握设计模式在PHP编程中的应用。设计模式是软件工程中经过时间验证的最佳实践,它们为解决常见问题提供了一种标准的方法,使...
2. **结构型模式**: - 适配器模式:使不兼容的接口能够协同工作。 - 组合模式:允许你将对象组合成树形结构来表示部分-整体层次结构。 - 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。 - 外观模式...
适配器模式(Adapter Pattern)是一种结构型设计模式,它主要解决的是接口不兼容的问题,使得原本由于接口差异无法一起工作的类能够协同工作。在PHP中,适配器模式通过创建一个包装类(适配器类)来转换不兼容的接口...
这种类型的设计模式属于结构型模式,它提供了一种替代继承机制的方法。 ##### 应用场景 - 动态增加功能 - 替代继承机制 - 扩展对象功能 #### 5. 适配器模式(Adapter Pattern) 适配器模式将一个类的接口转换成...
结构型模式则涉及对象的组合和封装,如装饰器模式、适配器模式和代理模式。行为型模式主要关注对象间的交互和责任分配,如观察者模式、策略模式和命令模式。 本书包含的源代码示例将帮助读者更好地理解这些模式的...
PHP设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。 1. **创建型模式**: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:提供一个接口来创建对象,但让子类决定实例化...
装饰器模式(Decorator Pattern)是一种结构型设计模式,主要用于在运行时动态地给对象添加新的职责或行为,而不必改变现有对象的类定义。在面向对象编程中,装饰器模式提供了一种相对于继承更加灵活的方式来增强或...
设计模式分为三大类:创建型模式、结构型模式和行为型模式。每种模式都针对软件设计中的特定问题,提供了最佳实践的解决方案。 1. **创建型模式**: - **单例模式**:确保一个类只有一个实例,并提供一个全局访问...
2. 结构型模式:这些模式处理对象组合和结构,如适配器(Adapter)、装饰器(Decorator)、代理(Proxy)、桥接(Bridge)、组合(Composite)、外观(Facade)和享元(Flyweight)。在PHP中,我们可以利用接口...
适配器模式是一种结构型设计模式,它的主要目的是使不兼容的接口能够协同工作。在实际开发中,我们可能会遇到这样的情况:一个类库或者服务提供了一个接口,而我们的代码需要使用另一个接口。适配器模式就充当了两者...
以下是根据标题“php设计模式案例汇总.zip”和描述中提到的九种创建型设计模式的详细解释: 1. 抽象工厂模式:它提供了一种创建相关或相互依赖对象的接口,而无需指定它们的具体类。在PHP中,抽象工厂常用于数据库...
结构型模式实例 改进模式 享元模式 外观模式 适配器模式 :check_mark_button: 装饰器模式 组合模式 代理模式 过滤器模式 行为型模式实例 模板模式 策略模式 :check_mark_button: 状态模式 观察者模式 :check_mark_...
2. 结构型模式:这些模式关注如何将类或对象组合成更大的结构,同时保持它们之间的松耦合。常见的结构型模式有适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、桥接模式(Bridge)、组合模式...
结构型模式如适配器模式、装饰器模式、代理模式等,关注如何组合不同的组件以构建更复杂的系统。行为型模式如策略模式、观察者模式、责任链模式等,关注对象间的行为和通信。 对于PHP开发者来说,理解这些模式并能...