java oop 测试题_实用的OOP:构建测验应用-自举

java oop 测试题

At a certain point of my development as a PHP programmer, I was building MVC applications by-the-book, without understanding the ins-and-outs. I did what I was told: fat model, thin controller. Don’t put logic in your views. What I didn’t understand was how to create a cohesive application structure that allowed me to express my business ideas as maintainable code, nor did I understand how to really separate my concerns into tight layers without leaking low-level logic into higher layers. I’d heard about SOLID principles, but applying them to a web app was a mystery.

在作为PHP程序员发展的某个时候,我是在不了解详细内容的情况下按书构建MVC应用程序的。 我被告知:胖模型,瘦控制器。 不要在您的观点中加入逻辑。 我不了解的是如何创建一个具有凝聚力的应用程序结构,该结构使我可以将我的业务想法表达为可维护的代码,也不了解如何将我的关注点真正分成紧密的层,而又不会将低级逻辑泄漏到高层。 我听说过SOLID原理,但是将其应用于Web应用程序是一个谜。

In this series, we’ll build a quiz application using these concepts. We’ll separate the application into layers, allowing us to substitute components: for example, it’ll be a breeze to switch from MongoDB to MySQL, or from a web interface to a command-line interface.

在本系列中,我们将使用这些概念来构建测验应用程序。 我们将应用程序分成几层,从而允许我们替换组件:例如,从MongoDB切换到MySQL,或从Web界面切换到命令行界面,都非常容易。

为什么MVC不够用: (Why MVC Isn’t Enough:)

MVC, which stands for Model-View-Controller, is a powerful design pattern for web applications. Unfortunately, with its rise to buzzword status, it has been taken out of context and used as a miracle cure. It’s become standard practice to use MVC frameworks, and many developers have succeeded in using them to seperate display logic and domain logic. The trouble is that developers stop there, building quasi-object-oriented systems at best and procedural code wrapped in classes–often controllers–at worst.

MVC代表模型-视图-控制器,是一种针对Web应用程序的强大设计模式。 不幸的是,随着它成为流行语 ,它已脱离上下文而被用作奇迹疗法。 使用MVC框架已成为标准做法,许多开发人员已成功使用它们来分离显示逻辑和域逻辑。 问题在于,开发人员会停在那里,最好是构建准面向对象的系统,而最坏的情况是将过程代码包装在类(通常是控制器)中。

In building our quiz app, we’ll be using the Domain Model pattern described in Martin Fowler’s Patterns of Enterprise Application Architecture. Domain Model is just a fancy way of saying that we’ll be using an object-oriented approach to designing the system: a web of objects with different responsibilities that as a whole, will comprise our application.

在构建测验应用程序时,我们将使用Martin Fowler的Enterprise Application Architecture模式中描述的Domain Model模式。 域模型只是一种奇特的说法,我们将使用面向对象的方法来设计系统:一个具有不同职责的对象网络,总体上将构成我们的应用程序。

The Domain Model approach uses “entity” objects to represent information in the database; but instead of having our object-oriented code mimic the database, we’ll have the database mimic our object-oriented design. Why? Because it allows us to build good object-oriented code. This mapping, called Object-Relational Mapping, is a large subject, and outside of the scope of this article. Luckily, there are several mature libraries available in PHP that solve this problem. The most mature of these, and my personal favorite, is Doctrine. We’ll be side-stepping the issue entirely by manually writing the specific mapping code we need for this article.

域模型方法使用“实体”对象来表示数据库中的信息。 但是我们不用让我们的面向对象的代码模仿数据库,而是让数据库模仿我们的面向对象的设计。 为什么? 因为它允许我们构建良好的面向对象的代码。 此映射称为对象关系映射,是一个很大的主题,不在本文讨论范围之内。 幸运的是,PHP提供了一些成熟的库来解决此问题。 其中最成熟的,也是我个人最喜欢的是教义 。 我们将通过手动编写本文所需的特定映射代码来完全避免该问题。

Even when using the Domain Model pattern, there is still the problem of performing operations that require multiple classes to work together. We’ll be solving this with the Service Layer pattern.

即使使用域模型模式,仍然存在执行需要多个类一起工作的操作的问题。 我们将使用“服务层”模式解决此问题。

服务层模式: (The Service Layer Pattern:)

Correct object-oriented design dictates that you should write decoupled code. Each class should have a single responsiblity. How, then, do we combine these independent classes to perform our business logic?

正确的面向对象设计要求您应该编写解耦的代码。 每个班级应该有一个责任。 那么,我们如何结合这些独立的类来执行业务逻辑呢?

The Service Layer pattern addresses this problem. We group all our system’s operations (signing up, purchasing a product, solving a quiz) into service classes, one service per operation or group of closely-related operations. We decouple these service classes from the classes to which they delegate. This allows us to reuse the services between different use-cases, say the web interface and the CLI interface, the front- and back-end interfaces, and so on.

服务层模式解决了这个问题。 我们将系统的所有操作(注册,购买产品,解决测验)分组为服务类,每个操作一个服务或一组紧密相关的操作。 我们将这些服务类从它们委托的类中分离出来。 这使我们能够在不同用例之间重用服务,例如Web界面和CLI界面,前端和后端界面,等等。

入门: (Getting Started:)

We’ll be using Slim as our MVC framework. Slim is a light-weight framework that’s easy to learn, and perfect for our simple app. As you’ll see in the next article, when we write controller code, it’ll be easy for you to replace Slim with any framework you prefer. We’ll install Slim with Composer. Create a directory for the project with the following composer.json file:

我们将使用Slim作为我们的MVC框架。 Slim是一个轻量级的框架,易于学习,非常适合我们的简单应用程序。 正如您将在下一篇文章中看到的那样,当我们编写控制器代码时,很容易将Slim替换为您喜欢的任何框架。 我们将在Composer中安装Slim。 使用以下composer.json文件为项目创建目录:

{
        "require": {
            "slim/slim": "2.*"
        }
        "autoload": {
            "psr-O": {"QuizApp\\": "./lib/"}
        }
    }

编码服务类别: (Coding the Service Class:)

We’ll need a service for handling the quiz flow: choosing a quiz, checking the user’s answers, and so on. This service will contain the bulk of the business logic of the application. The rest of the code will solve more technical, specific problems, such as accessing the database.

我们需要一种服务来处理测验流程:选择测验,检查用户的答案等等。 该服务将包含应用程序的大部分业务逻辑。 其余代码将解决更多技术性的特定问题,例如访问数据库。

Let’s define an interface for the service. Create a file lib/QuizApp/service/QuizInterface.php with the following contents:

让我们为服务定义一个接口。 使用以下内容创建文件lib/QuizApp/service/QuizInterface.php

<?php

namespace QuizApp\Service;

interface QuizInterface
{
    /** @return Quiz[] */
    public function showAllQuizes();

    public function startQuiz($quizOrId);

    /** @return Question */
    public function getQuestion();

    /** @return bool */
    public function checkSolution($id);

    /** @return bool */
    public function isOver();

    /** @return Result */
    public function getResult();
}

Most of the operations should speak for themselves, but getQuestion() and getResult() might not be so clear. getQuestion() returns the next question for the user to answer. getResult() returns an object with information about the number of correct and incorrect answers, and whether the user passed the quiz.

大多数操作都可以说明一切,但是getQuestion()getResult()可能不太清楚。 getQuestion()返回下一个问题供用户回答。 getResult()返回一个对象,该对象包含有关正确和不正确答案的数量以及用户是否通过了测验的信息。

Before we implement this service, we should define the mapper interface, as the service will need to use it. The service needs two operations: find() which returns a single quiz by ID, and findAll().

在实现此服务之前,我们应定义映射器接口,因为该服务将需要使用它。 该服务需要两个操作: find()通过ID返回单个测验;以及findAll()

<?php

    namespace QuizApp\Mapper;

    interface QuizInterface
    {
        /** @return \QuizApp\Entity\Quiz[] */
        public function findAll();

        /**
         * @param int $i
         * @return \QuizApp\Entity\Quiz
         */
        public function find($i);
    }

These operations return objects of the class \QuizApp\Entity\Quiz, which represents a single quiz. The Quiz class, in turn, contains \QuizApp\Entity\Question objects, which represent quiz questions. Let’s implement these before returning to the service.

这些操作返回\QuizApp\Entity\Quiz类的对象,该对象表示单个测验。 反过来, Quiz类包含\QuizApp\Entity\Question对象,它们表示测验问题。 让我们在返回服务之前实现这些。

<?php

    namespace QuizApp\Entity;

    class Question 
    {
        private $id;
        private $questions;
        private $solutions;
        private $correctIndex;

        /**
        * @param string $question
        * @param string[] $solutions
        * @param int $correctSolutionIndex
        */
        public function __construct ($question, array $solutions, $correctSolutionIndex)
        {
            $this->question = $question;
            $this->solutions = $solutions;
            $this->correctIndex = $correctSolutionIndex;
            if (!isset($this->solutions[$this->correctIndex])) {
                throw new \InvalidArgumentException('Invalid index');
            }
        }

        public function setId($id)
        {
            $this->id = $id;
        }

        public function getId()
        {
            return $this->id;
        }

        public function getQuestion()
        {
            return $this->question;
        }

        public function getSolutions()
        {
            return $this->solutions;
        }

        public function getCorrectSolution()
        {
            return $this->solutions[$this->correctIndex];
        }

        public function isCorrect($solutionId)
        {
            return $this->correctIndex == $solutionId;
        }
    }

Notice that, in addition to its getters and setters, \QuizApp\Entity\Question has a method isCorrect() for checking if a certain answer to the question is correct.

请注意,除了其getter和setter方法之外, \QuizApp\Entity\Question还具有isCorrect()方法,用于检查对该问题的某个答案是否正确。

And the \QuizApp\Entity\Quiz class:

\QuizApp\Entity\Quiz类:

<?php

    namespace QuizApp\Entity;

    class Quiz
    {
        private $id;
        private $title;
        private $questions;

        /**
        * @param string $title
        * @param Question[] $questions
        */
        public function __construct($title, array $questions)
        {
            $this->title     = $title;
            $this->questions = $questions;
        }

        public function setId($id)
        {
            $this->id = $id;
        }

        public function getId()
        {
            return $this->id;
        }

        public function getTitle()
        {
            return $this->title;
        }

        public function getQuestions()
        {
            return $this->questions;
        }
    }

And the \QuizApp\Service\Quiz\Result class:

\QuizApp\Service\Quiz\Result类:

<?php

    namespace QuizApp\Service\Quiz;

    class Result
    {
        private $correct;
        private $incorrect;
        private $passScore;

        public function __construct($correct, $incorrect, $passScore)
        {
            $this->correct = $correct;
            $this->incorrect = $incorrect;
            $this->passScore = $passScore;
        }

        public function getCorrect()
        {
            return $this->correct;
        }

        public function getIncorrect()
        {
            return $this->incorrect;
        }

        public function getTotal()
        {
            return $this->correct + $this->incorrect;
        }

        public function getPassScore()
        {
            return $this->passScore;
        }

        public function hasPassed()
        {
            return $this->correct >= $this->passScore;
        }
    }

编写占位符映射器: (Writing a Placeholder Mapper:)

We need a concrete \QuizApp\MapperMapper\MapperInterface class for the service to use. Let’s define a dummy implementation for the time being, so that we can test the code, before writing a real mapper that’ll access the MongoDB database. The dummy uses hard-coded ‘\QuizApp\Entity\Question’ objects to return from the find($id) and findAll() methods.

我们需要一个具体的\QuizApp\MapperMapper\MapperInterface类供服务使用。 让我们暂时定义一个虚拟实现,以便我们可以在编写将访问MongoDB数据库的真实映射器之前测试代码。 假人使用硬编码的'\ QuizApp \ Entity \ Question'对象从find($id)findAll()方法返回。

<?php

namespace QuizApp\Mapper;

class Hardcoded implements QuizInterface
{
    private static $MAP = array();

    /** @return \QuizApp\Entity\Quiz[] */
    public function findAll()
    {
        return [ $this->find(0), $this->find(1) ];
    }

    /**
     * @param int $id
     * @return \QuizApp\Entity\Quiz
     */
    public function find($id)
    {
        if (isset (self::$MAP[$id])) {
            return self::$MAP[$id];
        }
        $result = new \QuizApp\Entity\Quiz(
            'Quiz' . $id, [
                new \QuizApp\Entity\Question(
                    'What colour was George Washington\'s white horse?',
                    [ 'White', 'Gray', 'Yellow', 'All of the above' ],
                    0
                ),
                new \QuizApp\Entity\Question(
                    'Who\'s buried in Grant\'s tomb?',
                    [ 'Grant', 'George Washington', 'George Washingtion\'s horse', 'All of the above' ],
                    0
                ),
            ]
        );
        $result->setId($id);
        self::$MAP[$id] = $result;
        return $result;
    }
}

The class implements the interface by returning a couple of hard-coded Quiz objects. It uses the $MAP static property as an Identity Map to ensure the class returns the same objects each time it’s called.

该类通过返回几个硬编码的Quiz对象来实现该接口。 它使用$MAP静态属性作为Identity Map,以确保每次调用该类时都返回相同的对象。

结论: (Conclusion:)

In this first part of our Pratical OOP series we began developing our quiz application. We discussed MVC and why it is not a silver bullet; we covered the Domain Model and Service Layer design patterns; we sketched out the interface for our quiz service, which will contain the logic behind a user solving a quiz; we modeled the quizes and questions as entities; and we created a dummy mapper for looking up quizzes from the “database,” which will come in handy in part two.

在我们的实用OOP系列的第一部分中,我们开始开发测验应用程序。 我们讨论了MVC以及为什么它不是灵丹妙药。 我们介绍了域模型和服务层设计模式; 我们为测验服务草拟了界面,其中将包含用户解决测验的逻辑。 我们将测验和问题建模为实体; 我们创建了一个虚拟映射器,用于从“数据库”中查找测验,这将在第二部分中派上用场。

Stay tuned! Next time we’ll be be fleshing out our application, writing the service class, and a real database mapper that will connect to MongoDB. Once we have that in place, you’ll see how easy it is to write our controllers and views, and how our elegant design keeps the “M,” the “V,” and the “C” separate, maintainable, and extensible. You can find the full source code for this part here.

敬请关注! 下次,我们将充实我们的应用程序,编写服务类,以及将连接到MongoDB的真实数据库映射器。 一旦我们准备好了,您将看到编写我们的控制器和视图有多么容易,以及我们优雅的设计如何使“ M”,“ V”和“ C”保持独立,可维护和可扩展。 您可以在此处找到此部分的完整源代码。

翻译自: https://www.sitepoint.com/practical-oop-building-quiz-app-bootstrapping/

java oop 测试题

开发阳光旅行网app中用户下单功能,可实现用户添加订单并完善出行人信息、修改订单,删除订单以及打印行程信息等功能。 具体功能要求如下: (1)显示系统主菜单 包括添加出行订单、查看我的出行订单、修改订单信息、删除出行人、查看行程、退出系统6项功能,其他功能本项目不做要求,当用户选择功能编号后可进入执行相应功能。执行结果如图1所示。 图1 主菜单 (2)添加出行订单 填写出行日期、联系人手机号码、循环录入出行人信息。 出行人信息包括: 出行人类别:成人、儿童(1.2m以下)、老人(65岁以上) 姓名 年龄(如选择类别为老人,输入年龄不足65岁的,显示提示信息“对不起,老人订单年龄需为65岁以上!”) 如果是儿童,需确定是否占床 每成功录入一条出行人信息后,显示出其详细信息,并计算出行金额。定价如下: 成人:2000元/人 儿童:免费,如需占床另加30元 老人:半价,即1000元/人 当一条出行人信息录入完毕后,提示“是否继续添加(Y/N)?”,此处不区分大小写,当输入y或Y时继续录入下一条,否则显示订单信息,包括: 出行日期 联系人手机号码 订单总金额(即所有出行人定单金额之和) 最后显示主菜单。执行效果如图2所示。 图2 添加出行订单 (3)查看我的出行订单信息 查看我的出行订单:查看所录入的订单信息。包括出行日期、联系人手机号码、所有出行人信息,运行效果如图3所示。 图3 查看我的出行订单 (4)修改行程信息 可修改出行日期、联系人手机号码,要求手机号码必须为11位,否则抛出异常信息,提示“手机号码必须为11位”,运行效果如果4所示。 图4 手机号码不是11位 正确修改后,显示修改后的信息,并提示“修改成功!”。如图5所示。 图5 修改订单成功 (5)删除出行人 填写要删除的出行人姓名,执行删除操作,删除成功后给出提示“删除成功!”,如图6所示。如果输入姓名错误,则提示“对不起,定单中不包含此游客信息!”如图7所示。 图6 删除出行人成功 图7 删除出行人失败 (6)查看行程 显示本次旅行行程信息。运行效果如图8所示。 图8 查看行程 (7)退出系统 退出当前系统,显示“欢迎下次再来。”如图9所示。 三、要求与实现步骤 (一)不使用数据库,使用对象和集合存储数据 (二)定义实体类(成人订单、儿童订单、老人订单),儿童订单、老人订单为成人订单的子类。实体类至少包含但不局限于以上3个。 (三)在各实体类中均需实现各自计算订单价格、显示订单信息的方法,使用方法的重写。 (四)定义工具类,实现查看我的出行订单、添加订单、修改行程信息、删除出行人、查看行程等方法。需使用到对象传参。 (五)使用泛型集合存储所有出行人信息,使用集合的遍历实现查看订单信息、统计订单总金额、删除出行人等功能。 (六)显示信息时,只有儿童出行人需显示是否占座,需使用面向对象多态实现。 (七)修改行程信息时,当手机号码录入错误时需使用throw手动抛出异常。 (八)定义测试类,完成项目功能菜单以及整体流程,调用相应方法实现具体功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值