# 设计模式(php) **Repository Path**: fz-august/design_patterns ## Basic Information - **Project Name**: 设计模式(php) - **Description**: 学习设计模式 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-05-18 - **Last Updated**: 2024-11-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## PHP设计模式 为什么采用面向对象编程 1. 解决问题更容易。将大问题分解为小问题。 2. 模块化。 3. 加快开发和修改速度。 ## 相关概念 1. 类与对象 类:属性和方法 2. 单一职责 3. 签名 操作名(参数)--> 签名 3. 抽象: 接口和抽象类 抽象:指示一个对象的基本特征,与其他对象进行区分,从查看者的角度提供了清晰定义的概念边界 抽象类: 1. 不能实例化 2. 必须由具体类继承抽象类的接口 3. 可以包含具体方法 4. 可以包含属性 接口: 1. 不能包含属性,但可以包含常量 2. 不能包含具体的方法(只有签名,无具体实现) * 类型提示: 一般使用接口(接口和抽象类) 作为类型提示。 4. 特性 1. 封装 可见性控制 2. 继承 使用继承来获取某个类的属性和方法,同时可以进行自己的扩展。 3. 多态 多种形态。调用有相同接口的对象,完成不同的工作。 比如动物鸣叫的方法,dog类实现为'汪汪',猫为'喵喵'。 5. MVC 视图--控制器--模型 展示了松耦合,分离不同的元素来完成一个任务,提供了更大的灵活性。 ## 设计模式的原则 1. 按接口而不是按照实现来编程。 将变量设置为一个抽象类或者接口数据类型的实例,而不是一个具体实现的实例。 代码提示中使用接口(即签名)数据类型(只要实现了该接口,其输出都可以预测) 2. 应当优先选择组合而不是类继承。 继承: IS-A 组合:HAS-A 使用浅继承,避免修改父类影响到所有多层级的子类,导致未预期的错误。 使用委托(组合)可以有助于避免紧密绑定 ## 设计模式组织分类 1. 创建型 创建对象的模式。提供一些方法封装系统使用的具体类的有关知识,还可以隐藏实例创建和组合的相关信息。 2. 结构型 组合结构应当保证结构化。通过继承、组合对象建立新功能 3. 行为型 核心是算法和对象之间的职责分配。 4. 类模式 重点在于类和子类之间的关系。通过继承建立,是静态的,编译时已经固定。 5. 对象模式 对象模式强调的是可以在运行时可以改变的对象,更具有动态性。 * 设计模式是编程中反复出现的常见问题的解决方案,但是也不是一成不变的。 * 选择世界模式时需要考虑什么导致了重新设计?什么会变化(重点转化为封装那些变化的概念)? ## 创建型设计模式 1. 抽象工厂 2. 生成器 3. 工厂方法 client并不直接实例化请求的产品,而是由工厂负责实例化请求的产品。 使用场景:一个类无法预计它要创建的对象数目。 4. 原型 实现:通过复制原型实例创建新对象。 作用:原型设计模式通过使用克隆减少实例化对象的开销 5. 单例 4私一公,可以写成一个trait,方便复用 ## 结构型设计模式 结构性设计模式主要研究的是如何组合对象和类,来构成更大的结构。 1. 适配器模式(Adapter) 组合优于继承。参与者之间绑定更宽松,在重用、结构、修改等方面有很多优点。 就像要给手机充电一样,必须用usb数据线,将电脑或者插座插槽适配成为适合手机的端口。(功能一样,形式不同) 示例:网站--手机/PC端布局. 货币兑换 UML图: ![部门原型](https://github.com/mrfengz/php_practice/blob/master/design_patterns/structure/adapter.jpg) 2. 桥接模式(Bridge) 3. 组合模式(Composite) 4. 装饰器模式(Decorator) 为一个已有的结构增加“装饰”,而不影响其它其它对象。 适配器:为现有结构增加一个适配器类,用来处理不兼容的接口。 装饰器:向现有对象增加对象。抽象类(装饰器Decorator)继承另一个抽象类(Component) Component想成是空房间,地毯和家具看成是具体的装饰器。 UML图: ![装饰器类图](https://github.com/mrfengz/php_practice/blob/master/design_patterns/structure/decorator_1.png) 5. 外观模式(Pacade) 6. 享元模式(Flyweight) 7. 代理模式(Proxy) ## 行为型设计模式 行为型设计模式的关键是通信。对于这些模式,重点不再是构成一个设计模式的对象和类,而蝇转变成对象和类之间的对象。最好考虑对象如何相互合作来完成任务。 职责连模式(Chain of Responsibility) 命令模式(Command) 解释器模式(Interpreter) 迭代器模式(Iterator) 中介者模式(Mediator) 备忘录模式(Memento) 观察者模式(Observer) 状态模式(State) 允许对象在状态改变时改变其行为。 关键对象: Context/State/ConcreteStateA(B/C...) 一般通过条件语句判断状态改变 状态机 触发器:开关 状态:开灯、关灯 变迁:关灯-开灯,开灯-关灯 策略模式(Strategy) 模板方法模式(Template Method) 使用了一个类方法templateMethod(),是一个抽象类的具体方法,这个方法的具体作用是对抽象方法序列排序。但具体实现留给具体类来完成。定义了操作中算法的“骨架”。 类似与婚礼司仪的程序,但是具体形式可以由自己商量 UML图 ![模板方法类图](https://github.com/mrfengz/php_practice/blob/master/design_patterns/behavior/template/template_method1.png) 使用场景:已经明确算法的一些步骤,不过这些步骤可以采用多种不同的方法实现,就可以使用模板方法。 模板方法设计模式中的钩子 假设有一个模板方法,可以累加一个订单的总费用,另外加上税和运费,然后显示交易总金额。如果买家购买需要送货的商品超过200美元,可以免运费。就可以用到钩子。 使用场景: 模板方法中可能有一个你不想要的步骤,某些特定情况下你可能不希望执行这个步骤。 访问者模式 (Visitor) > 反向控制原则:父类调用子类的操作,而子类不调用父类的操作。 ## 注册树、单例和工厂模式 1. 单例模式解决的是整个请求中创建唯一对象实例的问题(每次创建前需要判断) 2. 工厂模式解决的是如何不通过new创建对象实力的方法(考虑的是扩展维护的问题) 3. 注册树模式,是将产生的对象统一‘插到’一棵树上,方便后续统一取用。 ********************************再学习******************************** #### 创建型 - 简单工厂 simple factory - 定义:生成一个对象的实例,而不向客户端公开任何实例化的逻辑 - 工厂方法 factory method - 定义:可以通过延伸出子类,实现用不同的方法创建对象。委托子类实现工厂方法 - demo: 定义一个创建实例的接口。比如LogFactory接口,子类有StdoutLoggerFactory 和 FileLoggerFactory。 - 何时使用:需要运行时动态决定使用哪个子类 - 抽象工厂 - 定义:抽象工厂模式提供了一种方法来封装一组具有共同主题的独立工厂,而无需指定它们的具体类 - demo: door-木门/铁门 fittingExpert-木匠/铁匠 doorFactory抽象类:makeDoor()/makeFittingExpert() - 何时使用:当存在不那么简单的创建逻辑相关的依赖时 - 构造器Builder - 定义:允许您创建对象的不同风格,同时避免构造函数污染。当一个对象可能有几种类型时很有用。或者当创建对象涉及很多步骤时。 - demo: - Burger-需要添加各种料,比如洋葱,番茄酱等 - 汽车:门、玻璃、车轮、动力源等 - 何时使用:当一个对象可能有几种类型时,避免构造函数伸缩。与工厂模式的关键区别是;当创建是一个单步骤过程时,将使用工厂模式,而当创建是一个多步骤过程时,将使用构建器模式。 - 原型模式 Prototype - 定义:基于已有对象创建一个新对象 clone - demo: Sheep-name/category, 克隆一个,设置新名字和category - 何时使用:当需要一个与现有对象类似的对象,或者创建比克隆开销大的对象时。 - 单例 Singleton - 定义:限制一个类仅有一个实例 - demo: President: private __construct/__clone/__invoke - 锁文件、日志记录器、数据库连接器 - 静态工厂 - 使用一个静态方法来创建所有它可以创建的类 #### 结构型 - 适配器 Adapter - 定义:适配器模式允许您将不兼容的对象包装在适配器中,以使其与另一个类兼容。防止修改已存在的类,同时可以使它可以在需要的地方应用 - demo: 插座-电源适配器-手机 - 桥接 Bridge - 定义:桥接模式更倾向于组合而不是继承。实现细节从一个层次结构推送到另一个具有独立层次结构的对象。 - demo: webpage-about/home/contact, 主题-dark/light/sweet, Page(Theme),将theme通过组合传递给Page - 组合 Composite - 定义:复合模式描述了一组对象将以与对象的单个实例相同的方式处理。组合的目的是将对象“组合”成树状结构,以表示部分-整体层次结构。实现复合模式让客户端可以统一地对待单个对象和组合。 - demo: 企业组织-员工-设计师/开发人员 Orgination(EmployeeInterface $employee) - 装饰器 Dcorate - 定义:它允许将行为静态或动态地添加到单个对象中,而不会影响同一类中其他对象的行为。装饰器模式对于遵守单一责任原则通常是有用的,因为它允许将功能划分到具有独特关注区域的类之间。装饰器模式允许您在运行时通过将对象包装在装饰器类的对象中来动态更改对象的行为 - 咖啡不同口味有不同的价格,新增了一个计价规则,比如自提和派送,需要一个新的计算价格的方法。 - 门面模式 - 定义:facade是一种对象,它为更大的代码体(如类库)提供了简化的接口。(facade的构造函数应该是接口,不要出现new) - demo: 电脑-开机/关机, 开机和关机有很多操作,但是给我们提供了turnOn和turnOff方法简化 - 轻量级对象 Flyweight - 定义:轻量级对象是通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象;当简单的重复表示将使用不可接受的内存时,它是一种使用大量对象的方法。 - demo: 茶饮商店-茶饮制造商-具体茶饮。 顾客购买时,一般做的茶比顾客需要的多,保存下来供其他顾客购买。 - 代理模式 Proxy - 定义:代理是由客户机调用的包装器或代理对象,用于访问幕后的实际服务对象。使用代理可以简单地转发到实际对象,也可以提供额外的逻辑。在代理中,可以提供额外的功能,例如在实际对象上的操作是资源密集型时进行缓存,或者在调用实际对象上的操作之前检查前提条件。 - demo:门-开/关, 增加代理类,检查是否有开门的权限。 #### 行为类 - 责任链 Chain of Responsibility - 定义:请求通过多道处理程序,从一个处理到下一个处理 - 计算可以用哪个账户购买。总共需要有1580元,A100元,B600元,C3000元,计算一下可以用哪个账户付款。 - 命令模式 Command - 定义:在这种模式中,一个对象被用来封装执行一个动作或在以后触发一个事件所需的所有信息。该信息包括方法名称、拥有方法的对象和方法参数的值。 - 灯泡类(Receiver)-开关命令类(Commander)-命令调用类(Invoker)。 - 迭代器模式 Iterator - 定义: 迭代器模式是一种设计模式,使用迭代器遍历容器并访问容器的元素。迭代器模式将算法与容器解耦;在某些情况下,算法必须是特定于容器的,因此不能解耦。 - 收音机,上/下一个频道 - 中介模式 Mediator - 定义:中介模式添加第三方对象(称为中介)来控制两个对象(称为同事)之间的交互。它有助于减少类之间相互通信的耦合。因为现在它们不需要知道彼此的实现。 - demo: 聊天:将message进行包装,返回时间:名字:发送内容 - 记忆模式 Memento - 定义:它提供了将对象恢复到以前状态(通过回滚撤消)的能力。 - demo: 编辑器+编辑器记忆器。编辑器保存时,保存到记忆器并返回。编辑器restore则调用记忆器的获取内容方法。 - 观察者模式 Observer - 定义:一个被称为主体的对象维护一个被称为观察者的依赖项列表,并在任何状态变化时自动通知它们,通常是通过调用它们的一个方法。 - demo: jobSeeker-subscribe(订阅者),jobSettings-Observers(观察者,维护订阅者列表),jobPoster-publisher(发布者) - 访问者模式 Visitor - 定义:访问者设计模式是一种将算法从其操作的对象结构中分离出来的方法。这种分离的一个实际结果是,可以在不修改现有对象结构的情况下向其添加新操作。这是遵循开放/封闭原则的一种方法 - demo: Animal-visitee, AnimalOperation(interface)-visitor,具体动物继承Animal,Speak继承AnimalOperation, 实例化Speak对象传给动物对象,就可以访问动物对象了。 - Strategy - 策略模式允许你基于不同的情况,切换算法或者策略 - demo: 排序算法。小数据冒泡排序,大数据快速排序 - State - 允许你在state改变的时候,有不同的行为 - demo: 画图应用的画笔,颜色不同时,画出来的图形颜色不同。 - 文本编辑器字体处理:默认常规字体,大小写使用不同的State标识并进行处理 - Template Method - 定义:操作步骤是固定的,但是每一个操作允许变动。定义某个算法的执行流程(Skeleton),但是推迟实现到其子类中。 - demo: 测试流程,test,lint, generate reports, deploy. - 建房子:打地基,盖墙体,搭屋顶。