您所在的位置:主页 > 培训巧问答 >

初学者的面向对象的概念:什么是抽象?

时间:2018-01-02 13:02来源:未知 作者:os 点击:

 
 
如果你不熟悉面向对象的原则,那么你会想了解更多关于面向对象的基本概念:抽象。
 
抽象是面向对象编程(OOP)语言的关键概念之一。其主要目标是通过隐藏用户不必要的细节来处理复杂性。这使得用户能够在所提供的抽象之上实现更复杂的逻辑,而不用理解甚至不考虑所有隐藏的复杂性。
 
这是一个非常通用的概念,不仅限于面向对象编程。你可以在现实世界的任何地方找到它。
现实世界中的抽象
我是一个咖啡瘾君子。所以,当我早晨醒来的时候,我走进厨房,打开咖啡机,煮咖啡。听起来有点熟?
 
用咖啡机制作咖啡就是一个很好的抽象例子。
 
你需要知道如何使用你的咖啡机来制作咖啡。你需要提供水和咖啡豆,打开它,并选择你想要的咖啡种类。
 
你不需要知道的是咖啡机是如何在内部工作来冲泡一杯美味的咖啡。您不需要知道水的理想温度或需要使用的咖啡粉的量。
 
有人担心这一点,并创建了一个咖啡机,现在作为一个抽象,并隐藏所有这些细节。您只需交互一个简单的界面,不需要任何关于内部实现的知识。
 
您可以在面向对象的编程语言(如Java)中使用相同的概念。
 
OOP中的抽象
OOP语言中的对象提供了隐藏内部实现细节的抽象。与厨房中的咖啡机类似,您只需要知道哪些对象的方法可以调用,哪些输入参数需要触发特定的操作。但是,您不需要了解如何实施此方法以及执行哪些操作来创建预期结果。
 
在Java中实现咖啡机示例。你在其他任何面向对象的编程语言中都是这样做的。语法可能有点不同,但一般的概念是相同的。
 
使用抽象来实现一台咖啡机
现代咖啡机变得相当复杂。根据您选择的咖啡,他们决定使用哪种咖啡豆以及如何磨碎咖啡豆。他们还使用适量的水,并将其加热到所需的温度,以冲泡一大杯过滤咖啡或一小杯浓咖啡。
 
实现CoffeeMachine抽象
使用抽象的概念,您可以在CoffeeMachine类中隐藏所有这些决定和处理步骤。如果你想保持尽可能简单,你只需要一个构造方法,需要一个地图 的CoffeeBean对象来创建一个新的CoffeeMachine对象和brewCoffee是希望你的方法CoffeeSelection并返回一个咖啡对象。
 
 
import org.thoughts.on.java.coffee.CoffeeException;
import java.utils.Map;
public class CoffeeMachine {
    private Map<CoffeeSelection, CoffeeBean> beans;
    public CoffeeMachine(Map<CoffeeSelection, CoffeeBean> beans) { 
         this.beans = beans
    }
    public Coffee brewCoffee(CoffeeSelection selection) throws CoffeeException {
        Coffee coffee = new Coffee();
        System.out.println(“Making coffee ...”);
        return coffee;
    }
}
 
CoffeeSelection是一个简单的枚举,为不同种类的咖啡提供一组预定义的值。
 
 
public enum CoffeeSelection { 
    FILTER_COFFEE, ESPRESSO, CAPPUCCINO;
}
 
 
CoffeeBean和Coffee类是简单的POJO(普通的旧Java对象),它们只存储一组属性而不提供任何逻辑。
 
public class CoffeeBean {
     private String name;
     private double quantity;
     public CoffeeBean(String name, double quantity) {
         this.name = name;
        this.quantity;
    }
}
public class Coffee {
    private CoffeeSelection selection;
    private double quantity;
    public Coffee(CoffeeSelection, double quantity) {
        this.selection = selection;
        this. quantity = quantity;
    }
}
 
使用CoffeeMachine抽象
使用CoffeeMachine类几乎就像早上喝咖啡一样简单。您只需要准备可用的CoffeeBean的Map ,实例化一个新的CoffeeMachine 对象,然后使用您首选的CoffeeSelection调用brewCoffee 方法。
 
 
import org.thoughts.on.java.coffee.CoffeeException;
import java.util.HashMap;
import java.util.Map;
public class CoffeeApp {
    public static void main(String[] args) {
        // create a Map of available coffee beans
        Map<CoffeeSelection, CoffeeBean> beans = new HashMap<CoffeeSelection, 
 
CoffeeBean>();
        beans.put(CoffeeSelection.ESPRESSO, 
            new CoffeeBean("My favorite espresso bean", 1000));
        beans.put(CoffeeSelection.FILTER_COFFEE, 
            new CoffeeBean("My favorite filter coffee bean", 1000));
        // get a new CoffeeMachine object
        CoffeeMachine machine = new CoffeeMachine(beans);
        // brew a fresh coffee
        try {
    Coffee espresso = machine.brewCoffee(CoffeeSelection.ESPRESSO);
} catch(CoffeeException  e) {
    e.printStackTrace();
        }
    } // end main
} // end CoffeeApp
 
你可以在这个例子中看到,CoffeeMachine 类提供的抽象隐藏了酿造过程的所有细节。这使得易于使用,并允许每个开发人员专注于特定的类。
 
如果您实施CoffeeMachine,则无需担心任何外部任务,例如提供杯子,接受订单或供应咖啡。其他人将在这方面的工作。你的任务是创建一个CoffeeMachine,使良好的咖啡。
 
而且,如果您实施使用CoffeeMachine的客户端,则不需要了解其内部进程的任何内容。其他人已经实现了它,以便您可以依靠其抽象在应用程序或系统中使用它。
 
这使得复杂应用程序的实现变得更加简单。而这个概念并不局限于你的班级的公共方法。每个系统,组件,类和方法提供了不同的抽象级别。您可以在系统的所有级别上使用它来实现高度可重用且
易于理解的软件。
 
不限于客户端API
让我们深入一下咖啡机项目,看看CoffeeMachine类的构造方法。
 
 
import java.util.Map;
public class CoffeeMachine {
    private Map<CoffeeSelection, Configuration> configMap;
    private Map<CoffeeSelection, CoffeeBean> beans;
    private Grinder grinder;
    private BrewingUnit brewingUnit;
    public CoffeeMachine(Map<CoffeeSelection, CoffeeBean> beans) {
        this.beans = beans;
        this.grinder = new Grinder();
        this.brewingUnit = new BrewingUnit();
        // create coffee configuration
        this.configMap = new HashMap<CoffeeSelection, Configuration>();
        this.configMap.put(CoffeeSelection.ESPRESSO, new Configuration(8, 28));
        this.configMap.put(CoffeeSelection.FILTER_COFFEE, new Configuration(30, 480));
    }
}
 
 
正如你在代码片断中看到的,构造函数不仅将提供的CoffeeBean的Map存储在内部属性中,还初始化一个内部Map,该Map 存储冲煮不同种类咖啡所需的配置,并实例化一个Grinder和BrewingUnit目的。
 
正如你在代码片段中看到的,构造函数不仅将提供的CoffeeBean的Map存储在内部属性中,还初始化一个内部Map,该Map存储冲煮不同咖啡所需的配置,并实例化一个Grinder和BrewingUnit目的。
 
所有这些步骤对构造函数方法的调用者不可见。开发者很可能甚至不知道磨床或BrewingUnit类存在。这是CoffeeMachine类提供的抽象的另一个例子。
 
每个类都提供自己的抽象
Grinder 和BrewingUnit 类自己提供抽象。该磨床 抽象研磨咖啡的复杂性和BrewingUnit 隐藏酿造过程的细节。
 
 
public class Grinder {
    public GroundCoffee grind(CoffeeBean coffeeBean, double quantityCoffee) { 
        // ... 
    }
}
public class BrewingUnit {
    public Coffee brew(CoffeeSelection selection, GroundCoffee groundCoffee, double 
 
quantity) {
        // ... 
    }
}
 
这使CoffeeMachine 类的实现变得容易很多。您可以实施brewCoffee方法,但不知道磨削或冲泡过程的任何细节。你只需要知道如何实例化这两个类,并调用研磨和冲泡方法。
 
同一类中不同的抽象级别
在这个例子中,我进一步抽象了一下,实现了三种方法来酿造不同种类的咖啡。由客户端调用的brewCoffee 方法只是对提供的CoffeeSelection 进行评估,并调用另一种方法来创建指定种类的咖啡。
 
该brewFilterCoffee和brewEspresso方法抽象冲泡咖啡所需的特定操作。
 
 
private Coffee brewFilterCoffee() {
    Configuration config = configMap.get(CoffeeSelection.FILTER_COFFEE);
    // grind the coffee beans
    GroundCoffee groundCoffee = this.grinder.grind(
        this.beans.get(CoffeeSelection.FILTER_COFFEE), config.getQuantityCoffee());
    // brew a filter coffee
    return this.brewingUnit.brew(
        CoffeeSelection.FILTER_COFFEE, groundCoffee, config.getQuantityWater());
}
private Coffee brewEspresso() {
    Configuration config = configMap.get(CoffeeSelection.ESPRESSO);
    // grind the coffee beans
    GroundCoffee groundCoffee = this.grinder.grind(
        this.beans.get(CoffeeSelection.ESPRESSO), config.getQuantityCoffee());
    // brew an espresso
    return this.brewingUnit.brew(
        CoffeeSelection.ESPRESSO, groundCoffee, config.getQuantityWater());
}
 
我将这两种方法都定义为私有方法,因为我只是想提供额外的内部抽象级别。这不仅使brewCoffee 方法的实现变得简单,而且提高了代码的可重用性。
 
例如,您可以在想要支持CoffeeSelection.CAPPUCCINO时重新使用brewEspresso 方法。然后你只需要执行所需的操作来加热牛奶,调用brewEspresso 方法来获得咖啡,并将其添加到牛奶中。
 
概要
抽象是一个一般的概念,你可以在现实世界以及在OOP语言中找到。现实世界中的任何对象,比如咖啡机,或者当前软件项目中的类,隐藏内部细节都会提供抽象。
 
这些抽象使得通过将其分解成更小的部分来处理复杂性变得容易得多。在最好的情况下,您可以使用它们而不理解它们如何提供功能。这不仅可以帮助您将下一个软件项目的复杂性分解为易于管理
的部分,还可以让您每天早上在您还在睡梦中时冲泡一杯新鲜的咖啡。
 
构建还是购买数据质量解决方案:哪个最适合您? 保持高质量的数据对于运营效率,有意义的分析和良好的长期客户关系至关重要。但是,在处理多个数据源时,数据质量变得复杂,因此您需要知
道何时应该为罐装解决方案构建定制的数据质量工具。下载我们的白皮书,以获取更多有关混合方法的见解。