我想通过实时示例学习设计模式。任何人都可以建议我可以从哪里开始。
4 回答
这些经典的设计模式每个开发者都应该了解,因为它帮助我们与其他开发者抽象层次的交流,让我们成为更好的设计师。
注意:添加带有真实生活和 Java API 示例的简短定义。
创造的
创建对象的方式。
原型:要复制或克隆的完全初始化实例
示例:国际象棋游戏的初始状态
java.lang.Object#clone()
Builder - 将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。
示例:当我们制作(或订购)披萨时(它的大小和口味可以不同)
- java.lang.StringBuilder
Singleton - 一个只能存在一个实例的类
示例:一个国家的总统
- java.lang.Runtime#getRuntime()
工厂方法- 创建一系列对象类型。
示例:在一个组织中,人力资源作为工厂方法工作。这里开发团队向 HR 请求资源类型。根据请求类型,HR 为开发团队提供资源。
- java.util.Calendar#getInstance()
Abstract Factory - 创建几个类系列的
实例 示例:HP、Samsung 和 Dell 笔记本电脑使用 Intel 和 AMD 处理器。
- javax.xml.parsers.DocumentBuilderFactory#newInstance()
结构
这种设计模式是关于类和对象组合的,即你想如何构建软件组件。这有助于我们保证当其中一个部件发生变化时,整个结构不需要改变。
代理- 代表另一个对象的对象。
示例:检查书页、信用卡、借记卡是 Money 和客户代表订购产品的代理。
- java.rmi.*,实际上是整个 API。
Composite - 为叶子和复合物提供统一的接口。
示例:操作系统中的文件系统,目录是复合的,文件是叶子。系统调用Open
是复合和叶子的单一接口。
装饰器- 为对象提供附加功能,同时提供统一的界面。
示例:1)在订单上添加d iscounts 2)枪本身就是一种致命的武器。但是你可以应用某些“装饰”来使它更准确、更安静和更具破坏性。
- java.io.InputStream、OutputStream、Reader 和 Writer 的所有子类都有一个构造函数,该构造函数采用相同类型的实例。
Facade - 代表整个子系统的单个接口。
示例:控制面板、事件管理器。
- javax.faces.context.ExternalContext,内部使用ServletContext、HttpSession、HttpServletRequest、HttpServletResponse等
Adapter - 为一个接口提供不同的接口。
示例:电源适配器
- java.util.Arrays#asList()
Flyweight - 用于高效共享的细粒度实例
示例:Flyweight 使用共享来支持大量对象高效 https://refactoring.guru/design-patternsly。公共交换电话网络是享元的一个例子。有多种资源,例如拨号音发生器、振铃发生器和数字接收器,必须在所有用户之间共享。当用户拿起听筒拨打电话时,他或她不知道池中有多少资源。对订户而言,重要的是提供拨号音、接收数字并完成呼叫。
- java.lang.Integer#valueOf(int) (也适用于布尔、字节、字符、短和长)
行为的
这种设计模式特别关注对象之间的通信。
责任链- 在对象链之间传递请求的一种方式
示例:贷款或休假审批流程,Java 中的异常处理。
- javax.servlet.Filter#doFilter()
迭代器- 按顺序访问集合的元素
示例:电视上的下一个/上一个按钮
- java.util.Iterator & java.util.Enumeration 的所有实现
状态- 当状态改变时改变对象的行为
示例:风扇墙控制
观察者- 一种通知更改多个类的方式
示例:投标或拍卖
- 发布/订阅 JMS API
访问者- 为类定义新操作,无需更改。示例:出租车
模板- 在操作中定义算法的骨架,并将一些步骤推迟到子类。
示例:蓝图
- java.io.InputStream、java.io.OutputStream、java.io.Reader和java.io.Writer的所有非抽象方法。
- java.util.AbstractList、java.util.AbstractSet 和 java.util.AbstractMap 的所有非抽象方法。
- javax.servlet.http.HttpServlet,默认情况下所有的 doXXX() 方法都会向响应发送 HTTP 405“方法不允许”错误。您可以自由实施任何一个或任何一个。
- Spring中的JMSTemplate HibernateTemplate和JdbcTemplate
命令- 将命令请求封装为对象
示例:餐厅的“客人检查”是命令模式的示例。服务员或女服务员接受客户的订单或命令,并通过将其写在支票上来封装该订单。然后将订单排队等待短期订单厨师。请注意,每个服务员使用的“检查”垫不依赖于菜单,因此他们可以支持烹饪许多不同项目的命令。
- java.lang.Runnable 的所有实现
Memento - 捕获和恢复对象的内部状态
示例:在游戏中保存状态和在 Windows 中撤消/重做操作
- java.io.Serializable 的所有实现
调解器- 定义类之间的简化通信
示例:空中交通管制员(ATC)
策略- 策略定义了一组可以互换使用的算法。
示例:运输方式
- java.util.Comparator#compare(),由 Collections#sort() 等执行。
- javax.servlet.http.HttpServlet、service() 和所有 doXXX() 方法采用 HttpServletRequest 和 HttpServletResponse 并且实现者必须处理它们(而不是将它们作为实例变量来获取!)。
- javax.servlet.Filter#doFilter()
现在这是一个会吸引很多反对票的答案。但我会告诉它任何方式。
我的建议是,“不要学习设计模式!!!”
通过坚持设计模式,你限制了你的创造力。此外,一些设计模式也有不好的一面,他们不会告诉你。例如,如果不小心使用,单例模式可能会导致问题。
此外,IMO,一些著名的设计模式是在考虑一种语言的情况下创建的,以解决该语言的特定问题。然而,像 Python 和 Javascript 这样的进化语言可以在不拘泥于设计模式的情况下非常惊人地使用。
与其学习设计模式,不如学习编程范式和内部概念。我将从维基百科复制粘贴以下列表,
- 允许副作用的命令式,
- 不允许副作用的功能性,
- 声明性的,它没有说明操作执行的顺序,
- 面向对象,将代码与代码修改的状态组合在一起,
- 将代码分组为函数的过程,
- 具有特定风格的执行模型的逻辑与特定风格的句法和语法相结合,以及
- 具有特定语法和语法风格的符号编程
当然,您可以通读标准设计模式以获得一些基本概念。但是不要从头到尾学习它们。它会破坏你的创造力。
如果您正在寻找 C# 设计模式,请参考:
“C# 设计模式教程”——Jame W Cooper