设为首页 加入收藏

TOP

接口使用的最佳时机(一)
2023-09-09 10:25:23 】 浏览:120
Tags:时机

1. 引言

接口在系统设计中,以及代码重构优化中,是一个不可或缺的工具,能够帮助我们写出可扩展,可维护性更强的程序。

在本文,我们将介绍什么是接口,在此基础上,通过一个例子来介绍接口的优点。但是接口也不是任何场景都可以随意使用的,我们会介绍接口使用的常见场景,同时也介绍了接口滥用可能带来的问题,以及一些接口滥用的特征,帮助我们及早发现接口滥用的情况。

2. 什么是接口

接口是一种工具,在识别出系统中变化部分时,帮助从系统模块中抽取出变化的部分,从而保证系统的稳定性,可维护性和可扩展性。接口充当了一种契约或规范,规定了类或模块应该提供的方法和行为,而不关心具体的实现细节。

接口通常用于面向对象编程语言中,如 JavaGo 等。在这些语言中,类可以实现一个或多个接口,并提供接口定义的方法的具体实现。通过使用接口,我们可以编写更灵活、可维护和可扩展的代码,同时将系统中的变化隔离开来。

接口的实现在不同的编程语言中可能会有所不同。以下简单展示接口在JavaGo 语言中的示例。在Go 语言中,接口是一组方法签名的集合。实现接口时,类不需要显式声明实现了哪个接口,只要一个类型实现了接口中的所有方法,就被视为实现了该接口。

// 定义一个接口
type Shape interface {
    Area() float64
    Perimeter() float64
}

// 实现接口的类型
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

Java 语言中,接口使用 interface 定义,同时包含所有的方法签名。类需要通过使用 implements 关键字来实现接口,并提供接口中定义的方法的具体实现。

// 定义一个接口
interface Shape {
    double area();
    double perimeter();
}

// 实现接口的类
class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }

    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

上面示例展示了JavaGo语言中接口的定义方式以及接口的实现方式,虽然具体实现方式各不相同,但它们都遵循了相似的概念,接口用于定义规范和契约,实现类则提供方法的具体实现来满足接口的要求。

3. 接口的优点

在识别出系统变化的部分后,接口能够帮助我们将系统中变化的部分抽取出来,基于此能够降低了模块间的耦合度,能够提高代码的可维护性和代码的模块化程度,有助于创建更灵活、可扩展和易于维护的代码。下面我们通过一个简单的例子来进行说明,详细讨论这些好处。

3.1 初始需求

假设我们在构建一个商城系统,其中一个相对复杂且重要的模块为商品价格的计算,计算购物车中各种商品的总价格。价格计算过程相对复杂,包括了基础价格、折扣、运费的计算,然后每一块内容都会有比较复杂的业务逻辑。

基于此设计了OrderProcessor结构体,其中的CalculateTotalPrice 实现商品价格的计算,设计了ShippingCalculator 来计算运费,同时还设计DiscountCalculator 来计算商品的折扣信息,通过这几部分的交互配合,共同来完成商家价格的计算。

image.png

下面我们通过一段代码来展示上面的计算流程:

type OrderProcessor struct {
        discountCalculator DiscountCalculator
        taxCalculator      TaxCalculator
}

// 计算总价格
func (tpc OrderProcessor) CalculateTotalPrice(products []Product) float64 {
        total := 0.0
        for _, item := range cart {
                // 获取商品的基础价格
                basePrice := item.BasePrice
                // 获取适用于商品的折扣
                discount := tpc.discountCalculator.CalculateDiscount(item)
                // 计算运费
                shippingCost := tpc.shippingCalculator.CalculateShippingCost(item)
                // 计算商品的最终价格(基础价格 - 折扣 + 税费 + 运费)
                finalPrice := basePrice - discount + shippingCost
                total += finalPrice
        }
        return total
}

// 运费计算
type ShippingCalculator struct {}
func (sc ShippingCalculator) CalculateShippingCost(product Product) float64 {
     return 0.0
}

// 折扣计算
type DiscountCalculator struct {}
func (dc DiscountCalculator) CalculateDiscount(product Product) float64 {
      return 0.0 
}

如果这里需求没有发生变化,这个流程可以很好得运转下去。假设这里需要根据商品的类型来应用不同的折扣,之后要怎么支持呢,可以对变化的部分抽取出一个接口,也可以不抽取,都可以支持,我们比较一下没有使用接口和使用接口的两种实现方式的区别。

3.2 不抽象接口

首先是不使用接口的实现,这里我们直接在DiscountCalculator 中叠加逻辑,支持不同类型商品的折扣:

type DiscountCalculator struct{}

func (dc DiscountCalculator) CalculateDiscount(product Product) float64 {
        // 根据商品类型应用不同的折扣逻辑
        switch product.Type {
        case "TypeA":
                return dc.calculateTypeADiscount(product)
        case "TypeB":
                return dc.calculateTypeBDiscount(product)
        default:
                return dc.calculateDefaultDiscount(product)
        }
}

func (dc DiscountCalculator) calculateTypeADiscount(product Product) float64 {
        // 计算 TypeA 商品的折扣
        return product.BasePrice * 0.1 // 例如,假设 TypeA 商品有 10% 的折扣
}

fu
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Go 语言内置类型全解析:从布尔到.. 下一篇go基础-函数

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目