17天 - 谈谈你了解的最常见的几种设计模式,说说他们的应用场景? 你认为好的代码应该是什么样的?工厂模式和抽象工厂模式有什么区别?

谈谈你了解的最常见的几种设计模式,说说他们的应用场景

1. 单例模式(Singleton Pattern)

  • 介绍:确保一个类只有一个实例,并提供一个全局访问点。
  • 应用场景
    • 配置管理:系统中需要一个全局配置对象来存储设置,如数据库连接信息等。
    • 日志记录:创建一个全局日志记录器,统一管理日志输出。

2. 工厂模式(Factory Pattern)

  • 介绍:定义一个创建对象的接口,但由子类决定实例化哪一个类。
  • 应用场景
    • 对象创建复杂:当创建对象需要大量重复代码时,封装在工厂中简化创建逻辑。
    • 系统扩展:当系统需要扩展新对象时,只需添加新工厂,无需修改原有代码。
    • 需要控制资源:如数据库连接池,控制同时创建的连接数。

3. 观察者模式(Observer Pattern)

  • 介绍:定义对象间的一对多依赖关系,当一个对象状态变化时,所有依赖对象自动更新。
  • 应用场景
    • 事件驱动系统:GUI程序中,按钮点击事件可被多个监听器观察处理。
    • 数据绑定:前端框架中,数据模型变化自动更新视图。
    • 消息订阅:系统中部分对象需订阅另一对象消息,如新闻订阅、邮件通知等。

4. 策略模式(Strategy Pattern)

  • 介绍:定义一系列算法,将每个算法封装起来,使它们可以互换。
  • 应用场景
    • 算法切换:系统需动态切换算法,如计算运费时根据订单重量选择不同运费计算策略。
    • 解耦算法:使算法与使用它代码独立,便于维护扩展,如排序策略选择。
    • 策略配置:根据配置文件或用户输入选择策略,如不同促销策略配置。

5. 适配器模式(Adapter Pattern)

  • 介绍:将一个类的接口转换成客户希望的另一个接口。
  • 应用场景
    • 系统集成:将旧系统接口转换为新系统所需接口,使新旧系统兼容。
    • 类库复用:使因接口不兼容而不能一起使用的类合作,如将不同数据库接口统一。
    • 框架开发:提供固定接口,通过适配器模式兼容不同组件。

6. 装饰器模式(Decorator Pattern)

  • 介绍:动态地给对象增加额外职责,比子类化更灵活。
  • 应用场景
    • 功能扩展:在不修改原对象前提下,动态添加功能,如Java IO流操作中对输入输出流功能增强。
    • 灵活组合:多种装饰可组合使用,实现功能灵活组合,如咖啡店按不同配料组合咖啡。
    • 避免代码冗余:替代过多子类,减少冗余代码。

7. 代理模式(Proxy Pattern)

  • 介绍:为其他对象提供一种代理以控制对这个对象的访问。
  • 应用场景
    • 远程代理:透明化远程对象访问,本地代码无需关心对象在远程机器。
    • 虚拟代理:对重资源对象提供临时占位符,按需加载。
    • 保护代理:控制不同权限用户对对象访问,如管理员和普通用户。

8. 模板方法模式(Template Method Pattern)

  • 介绍:定义一个操作中的算法骨架,将一些步骤延迟到子类中。
  • 应用场景
    • 框架搭建:框架提供通用流程,允许子类覆盖具体步骤,如Web框架统一处理HTTP请求流程。
    • 代码复用:相同代码封装在模板方法,具体子类复用,减少重复代码。
    • 流程控制:固定流程顺序,让子类控制部分步骤,如产品制作流程。

9. 命令模式(Command Pattern)

  • 介绍:将请求封装为对象,使可用不同的请求对客户进行参数化。
  • 应用场景
    • 命令队列:将多个命令放入队列依次执行,如批处理任务。
    • 日志恢复:记录命令执行,便于恢复撤销,如Word中撤销命令。
    • 远程控制:将命令对象传输到远程执行,如远程服务器管理。

你认为好的代码应该是什么样的?

1. 可读性高

  • 清晰的命名:变量名、函数名、类名应该清晰易懂,能够准确表达其用途。例如,用userName而不是x来表示用户姓名。
  • 格式规范:代码应遵循一致的缩进、空格、括号等格式规范,便于阅读和理解。
  • 注释简洁:适当添加注释,解释代码的关键逻辑和复杂部分,但避免过多冗余注释。

2. 可维护性强

  • 模块化设计:代码应分为多个模块或函数,每个模块有明确的职责,便于独立开发和维护。
  • 低耦合高内聚:模块之间的依赖关系应尽量少,模块内部的逻辑应紧密相关。
  • 易于修改:代码在需求变更时,能够快速定位问题并进行修改,而不会影响其他功能。

3. 功能完整

  • 满足需求:代码应完全实现需求文档中规定的所有功能,且功能能够正常运行。
  • 处理异常:能够处理各种正常和异常情况,如用户输入错误、网络连接失败等。
  • 鲁棒性强:对非法输入或意外情况有良好的处理机制,不会导致程序崩溃。

4. 可扩展性好

  • 易于扩展:代码设计应考虑未来可能的功能扩展,新的功能能够方便地添加而不破坏现有结构。
  • 灵活配置:尽量使用配置文件或参数化设计,使代码能够适应不同的运行环境。

5. 性能优化

  • 高效执行:代码应尽可能减少时间复杂度和空间复杂度,提高程序运行效率。
  • 资源合理:合理使用系统资源,避免资源浪费,如及时释放文件句柄、数据库连接等。
  • 响应快速:对于用户交互的程序,响应时间应尽量短,提高用户体验。

6. 安全性高

  • 防止漏洞:代码应防止常见的安全漏洞,如SQL注入、跨站脚本攻击(XSS)等。
  • 数据保护:对敏感数据进行加密存储和传输,确保数据安全。
  • 权限控制:合理设置用户权限,防止未授权访问。

7. 可测试性强

  • 单元测试:代码应易于编写单元测试,每个函数或模块能够独立测试。
  • 接口清晰:模块之间的接口应清晰明了,便于测试和集成。
  • 测试覆盖:测试用例应覆盖主要的功能路径和异常情况,确保代码质量。

8. 文档完善

  • 代码注释:适当添加注释,解释代码的关键逻辑和复杂部分。
  • 设计文档:提供详细的设计文档,包括系统架构、模块功能、接口说明等。
  • 使用文档:提供用户手册或帮助文档,便于用户理解和使用程序。

9. 符合团队规范

  • 统一风格:团队内代码风格应统一,便于团队协作和代码审查。
  • 代码审查:定期进行代码审查,确保代码质量符合团队标准。

工厂模式和抽象工厂模式有什么区别?

工厂模式(Factory Pattern)

定义

工厂模式提供一个接口,用于创建一个对象,但由子类决定实例化哪一个类。它将对象的创建推迟到子类。

结构
  • 工厂接口或类:定义创建对象的接口。
  • 具体工厂:实现工厂接口,创建具体的产品对象。
  • 产品接口或抽象类:定义产品的接口。
  • 具体产品:实现产品接口,是实际被创建的对象。
示例
class Product:
    def use(self):
        pass

class ConcreteProductA(Product):
    def use(self):
        print("Using Product A")

class ConcreteProductB(Product):
    def use(self):
        print("Using Product B")

class Factory:
    def create_product(self, type):
        if type == "A":
            return ConcreteProductA()
        elif type == "B":
            return ConcreteProductB()
        else:
            raise ValueError("Unknown product type")

# 使用工厂模式
factory = Factory()
product = factory.create_product("A")
product.use()  # 输出:Using Product A

抽象工厂模式(Abstract Factory Pattern)

定义

抽象工厂模式提供一个接口,用于创建一系列相关或依赖的对象,而无需指定它们的具体类。它强调的是创建一系列对象,而不是单一对象。

结构
  • 抽象工厂接口:定义创建一系列产品的接口。
  • 具体工厂:实现抽象工厂接口,创建具体的产品对象。
  • 抽象产品接口或抽象类:定义一系列产品的接口。
  • 具体产品:实现抽象产品接口,是实际被创建的对象。
示例
class AbstractProductA:
    def use(self):
        pass

class AbstractProductB:
    def use(self):
        pass

class ConcreteProductA1(AbstractProductA):
    def use(self):
        print("Using Product A1")

class ConcreteProductB1(AbstractProductB):
    def use(self):
        print("Using Product B1")

class ConcreteProductA2(AbstractProductA):
    def use(self):
        print("Using Product A2")

class ConcreteProductB2(AbstractProductB):
    def use(self):
        print("Using Product B2")

class AbstractFactory:
    def create_product_a(self):
        pass

    def create_product_b(self):
        pass

class ConcreteFactory1(AbstractFactory):
    def create_product_a(self):
        return ConcreteProductA1()

    def create_product_b(self):
        return ConcreteProductB1()

class ConcreteFactory2(AbstractFactory):
    def create_product_a(self):
        return ConcreteProductA2()

    def create_product_b(self):
        return ConcreteProductB2()

# 使用抽象工厂模式
factory1 = ConcreteFactory1()
product_a1 = factory1.create_product_a()
product_b1 = factory1.create_product_b()
product_a1.use()  # 输出:Using Product A1
product_b1.use()  # 输出:Using Product B1

主要区别

  1. 创建对象的复杂度
    • 工厂模式:用于创建单一对象,根据参数决定创建哪种类型的对象。
    • 抽象工厂模式:用于创建一系列相关对象,强调对象之间的关联性。
  2. 接口的复杂度
    • 工厂模式:工厂类通常有一个单一的创建方法。
    • 抽象工厂模式:工厂接口包含多个创建方法,每个方法对应一种类型的产品。
  3. 适用场景
    • 工厂模式:适用于需要动态创建对象的场景,且对象类型在运行时确定。
    • 抽象工厂模式:适用于需要创建一系列相关对象的场景,且这些对象需要保持一致性或依赖性。

总结

  • 如果你的系统需要动态创建对象,并且对象类型在运行时确定,使用工厂模式
  • 如果你的系统需要创建一系列相关对象,并且这些对象需要保持一致性或依赖性,使用抽象工厂模式
  • 抽象工厂模式在结构上比工厂模式更复杂,但提供了更高的灵活性和扩展性,适用于更复杂的对象创建场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值