【OOP】面向对象实战训练,登录、注册、买票、查询、删改等业务场景后端设计

简介: 面向对象实战训练

前言

这是老师带着敲的项目,主要锻炼面向对象思想的实现,针对不同场景应该用什么样的集合容器来存储数据,什么时候该用泛型,什么时候该用分支控制语句,什么时候要避免使用if-else.
进一步理解所谓的通过继承提高程序的扩展性,复用性,以及封装类来保证数据的安全性、一致性,特别是无时无刻都在体现多态

一、实体抽象为对象(🚩)

这是面向对象设计的过程中画出来的分层设计图,把两个实体Movie、User当作两个对象,每一个对象看作一个类来处理,由于系统用户存在商家和客户两类,所以通过继承父类User的形式来实现
在这里插入图片描述
定义一个电影类Movie类,Movie类包含:片名、主演、评分、时长、票价、余票系统包含2个用户角色:客户、商家。存在大量相同属性信息
定义User类作为父类,属性:登录名称、密码、真实名称、性别、电话、账户金都定义Business类代表商家角色,属性:店铺名称、地址
定义Customer类代表客户角色,没有额外属性
定义集合List<User>用户存放系统注册的用户对象信息
定义集合Map<Business, List<Movie>>存放商家和其排片信息
==注意==昨天看面试直播中就问到“保存一个人和他的相关信息采用ArrayList、LinkedList还是HashMap”,针对此种场景和本项目,都应该采用Map双列集合来存取,因为Business和Movie对象两者是K-V的映射关系

二、对象封装成类

1.用户User类

这里的loginName目的是用来设置曾用名,在登陆的时候用来和用户输入的userName做对比来实现用户名是否输入正确的目的

public class User {
    private String loginName;  // 方便以后设置的曾用名
    private String userName; // 真名
    private String passWord;
    private char sex;
    private String phone;
    private double money;
    public User(){
    }
    public User(String loginName, String userName, String passWord, char sex, String phone, double money) {
        this.loginName = loginName;
        this.userName = userName;
        this.passWord = passWord;
        this.sex = sex;
        this.phone = phone;
        this.money = money;
    }
    public String getLoginName() {return loginName;}
    public void setLoginName(String loginName) {this.loginName = loginName;}
    public String getUserName() {return userName;}
    public void setUserName(String userName) {this.userName = userName;}
    public String getPassWord() {return passWord;}
    public void setPassWord(String passWord) {this.passWord = passWord;}
    public char getSex() {return sex;}
    public void setSex(char sex) {this.sex = sex;}
    public String getPhone() {return phone;}
    public void setPhone(String phone) {this.phone = phone;}
    public double getMoney() {return money;}
    public void setMoney(double money) {this.money = money;}
}

2.商户Business类

Business是User类的一个子类,但是他存在私有属性shopName、adress

public class Business extends User{  
    private String shopName;       // 门店名称
    private String address;        // 门店地址
    public String getShopName() {return shopName;}
    public void setShopName(String shopName) {this.shopName = shopName;}
    public String getAddress() {return address;}
    public void setAddress(String address) {this.address = address;}
}

3.顾客Customer类

同时属于User类的子类,这里定义了一个Map类型的buyMovies来存储购买记录

public class Customer extends User{
    // 定义一个属性存储购买记录
  private Map<String, Boolean> buyMovies = new HashMap<>();
  public Map<String, Boolean> getBuyMovies() {return buyMovies;}
  public void setBuyMovies(Map<String, Boolean> buyMovies) {this.buyMovies = buyMovies;}
}

4.电影Movie类

在设置电影属性的get、set方法之后我们还要针对电影的评分功能做一个升级,具体是通过List集合把MovieSystem中用户输入的评分转成一个double类型的数据存在其中,然后调用get方法时返回出来

public class Movie {
    private String name;
    private String actor;
    private double time;
    private double price;
    private int number; 
    private Date startTime; 
    public Movie() {}
    public Movie(String name, String actor, double time, double price, int number, Date startTime) {
        this.name = name;
        this.actor = actor;
        this.time = time;
        this.price = price;
        this.number = number;
        this.startTime = startTime;
    }
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getActor() {return actor;}
    public void setActor(String actor) {this.actor = actor;}
    public double getScore() {
        List<Double> scores = MovieSystem.MOVIES_SCORE.get(name);
        if(scores!=null && scores.size() > 0){
            double sum = 0;
            for (Double score : scores) {
                sum += score;
            }
            return BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(scores.size()), 2 , RoundingMode.UP).doubleValue();
        }else {
            return 0;
        }
    }
    public double getTime() {return time;}
    public void setTime(double time) {this.time = time;}
    public double getPrice() {return price;}
    public void setPrice(double price) {this.price = price;}
    public int getNumber() {return number;}
    public void setNumber(int number) {this.number = number;}
    public Date getStartTime() {return startTime;}
    public void setStartTime(Date startTime) {this.startTime = startTime;}
}

三、业务功能实现类

1.设置全局变量

存储用户对象的List
public static final List<User> allUserS = new ArrayList<>();
存储商家和电影信息的Map
public static final Map<Business, List<Movie>>allMovies = new HashMap<>();
处理用户输入的变量
public static final Scanner userInfo = new Scanner(System.in);
登陆用户对应的对象
public static User loginUser;
时间变量
public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

2.首页展示

首页可以通过用户输入的指令,执行相应的业务(登陆、注册)登陆成功会进入后台去买票

    private static void showMain() {
        while (true) {
            System.out.println("===============电影首页=================");
            System.out.println("1、用户登录");
            System.out.println("2、用户注册");
            System.out.println("请输入操作命令:");
            String key = userInfo.nextLine();
            switch (key) {
                case "1":
                    // 登录
                    login();
                    break;
                case "2":
                    //注册
                    register();
                    break;
                default:
                    System.out.println("不是内部命令!请重新输入!");
            }
        }
    }

2.1用户登录(🚩)

这里的对登陆的用户是否先前存在的验证方式是:
调用getUserByLoginName()方法,向其形参列表中传入用户名,然后在方法内部遍历一遍存储User对应的List集合并进行比较,如果有就返回这个对象,如果没有就返回null,而反回null导致的结果就是if不成立,登陆失败
当登陆成功,也就是遍历匹配到了对应类型,会返回这个对象user然后继续比较
若是Business类型则会进入商家后台,若是Customer类型则会进入买票后台

private static void login() {
        while (true) {
            System.out.println("请您输入登录名称:");
            String loginName = userInfo.nextLine();
            System.out.println("请您输入登录密码:");
            String passWord = userInfo.nextLine();

            // 1、根据登录名称查询用户对象。
            User user = getUserByLoginName(loginName);
            // 2、判断用户对象是否存在,存在说明登录名称正确了
            if(user != null){
                // 3、比对密码是否正确
                if(user.getPassWord().equals(passWord)){
                    // 登录成功了:...
                    loginUser = user; // 记住登录成功的用户
                    // 判断是用户登录的,还是商家登录的。
                    if(user instanceof Customer) {
                        // 用户登录
                        showCustomerMain();
                    }else {
                        // 商户登录
                        showBusinessMain();
                    }
                    return;
                }else {
                    System.out.println("密码错误!");
                }
            }else {
                System.out.println("登录名称错误!");
            }
        }
    }

验证方法:
遍历集合查找是否存在和曾用名相同的String类型的值

    public static User getUserByLoginName(String loginName){
        for (User user : allUserS) {
            // 判断输入用户名是否存在
            if(user.getLoginName().equals(loginName)){
                return user;
            }
        }
        return null; // 查询此用户登录名称
    }

2.2用户注册

    private static void register() {

        System.out.println("请注册名称:");
        String loginName = userInfo.nextLine();
        System.out.println("请设置密码:");
        String passWord = userInfo.nextLine();
        System.out.println("请设置昵称:");
        String userName = userInfo.nextLine();
        System.out.println("请设置资产:");
        double userMoney = userInfo.nextDouble();
        System.out.println("请留下电话:");
        String userPhone = userInfo.nextLine();

        Customer cus = new Customer();
        cus.setLoginName(loginName);
        cus.setPassWord(passWord);
        cus.setUserName(userName);
        cus.setMoney(userMoney);
        cus.setPhone(userPhone);
        allUserS.add(cus);

    }

3.商家后台

比较有意思的是这里用到了三元运算符实现性别输出的判断

 private static void showBusinessMain() {
        while (true) {
            System.out.println("============后台电影界面===================");
            System.out.println
            (loginUser.getUserName() + (loginUser.getSex()=='男'? "先生":"女士" + "欢迎您进入系统"));
            System.out.println("1、展示详情:");
            System.out.println("2、上架电影:");
            System.out.println("3、下架电影:");
            System.out.println("4、修改电影:");
            System.out.println("5、退出:");
            System.out.println("请输入您要操作的命令:");
            String command = userInfo.nextLine();
            switch (command){
                case "1":
                    // 展示全部电影
                    showBusinessInfos();
                    break;
                case "2":
                    // 上架电影
                    addMovie();
                    break;
                case "3":
                    // 下架电影
                    deleteMovie();
                    break;
                case "4":
                    // 修改电影
                    updateMovie();
                    break;
                case "5":
                    System.out.println(loginUser.getUserName() +"请您下次再来啊~~~");
                    return; 
                default:
                    System.out.println("不是内部命令!!");
                    break;
            }
        }
    }

3.1展示排片情况

利用Movie类中的get方法得到对应信息

private static void showBusinessInfos() {
        System.out.println("================商家详情界面=================");
        LOGGER.info(loginUser.getUserName() +"商家,正在看自己的详情~~~");
        // 商家对象作为Map集合的键 提取对应的值就是其排片信息 
        Business business = (Business) loginUser;
        System.out.println(business.getShopName() + "\t\t电话:" + business.getPhone()
                + "\t\t地址:" + business.getAddress() + "\t\t余额:" + business.getMoney());
        List<Movie> movies = allMovies.get(business);
        if(movies.size() > 0) {
            System.out.println("片名\t\t\t主演\t\t时长\t\t评分\t\t票价\t\t余票数量\t\t放映时间");
            for (Movie movie : movies) {
                System.out.println(movie.getName()+"\t\t\t" + movie.getActor()+ "\t\t" + movie.getTime()
                        + "\t\t" + movie.getScore() + "\t\t" + movie.getPrice() + "\t\t" + movie.getNumber() + "\t\t"
                        +   sdf.format(movie.getStartTime()));
            }
        }else {
            System.out.println("您的店铺当前无片在放映~~~~");
        }
    }

3.2商家上架电影

private static void addMovie() {
        System.out.println("================上架电影====================");  
        Business business = (Business) loginUser;
        List<Movie> movies = allMovies.get(business);

        System.out.println("请您输入新片名:");
        String name  = userInfo.nextLine();
        System.out.println("请您输入主演:");
        String actor  = userInfo.nextLine();
        System.out.println("请您输入时长:");
        String time  = userInfo.nextLine();
        System.out.println("请您输入票价:");
        String price  = userInfo.nextLine();
        System.out.println("请您输入票数:");
        String totalNumber  = userInfo.nextLine(); // 200\n
        while (true) {
            try {
                System.out.println("请您输入影片放映时间:");
                String stime  = userInfo.nextLine();
                Movie movie = new Movie(name, actor ,Double.valueOf(time) , Double.valueOf(price)
                , Integer.valueOf(totalNumber) ,  sdf.parse(stime));//封装
                movies.add(movie);
                System.out.println("上架成功:《" + movie.getName() + "》");
                return; // 直接退出去
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
  }

3.3商家下架电影

private static void deleteMovie() {
        System.out.println("================下架电影====================");
        Business business = (Business) loginUser;
        List<Movie> movies = allMovies.get(business);
        if(movies.size() == 0) {
            System.out.println("当期无片可以下架~~");
            return;
        }
        while (true) {
            System.out.println("请您输入需要下架的电影名称:");
            String movieName = userInfo.nextLine();

            // 3、去查询有没有这个影片对象。
            Movie movie = getMovieByName(movieName);
            if(movie != null){
                // 下架它
                movies.remove(movie);
                System.out.println("您当前店铺已经成功下架了:" + movie.getName());
                showBusinessInfos();
                return;
            }else {
                System.out.println("您的店铺没有上架该影片!");
                System.out.println("请问继续下架吗?y/n");
                String command = userInfo.nextLine();
                switch (command) {
                    case "y":
                        break;
                    default:
                        System.out.println("好的!");
                        return;
                }
            }
        }
    }

3.4修改电影信息

    private static void updateMovie() {
        System.out.println("================修改电影====================");
        Business business = (Business) loginUser;
        List<Movie> movies = allMovies.get(business);
        if(movies.size() == 0) {
            System.out.println("当期无片可以修改~~");
            return;
        }

4.用户后台

4.1顾客买票(🚩)

在这里插入图片描述

private static void buyMovie() {
 showAllMovies();
 System.out.println("=============用户购票功能=================");
 while (true) {
System.out.println("请您输入需要买票的门店名:");
String shopName = userInfo.nextLine();
// 1、查询是否存在该商家。
Business business = getBusinessByShopName(shopName);
if (business == null) {
 System.out.println("这家店倒闭啦~");
} else {
 // 2、此商家全部的排片
 List<Movie> movies = allMovies.get(business);
 // 3、判断是否存在上映的电影
 if (movies.size() > 0) {
     // 4、开始进行选片购买
     while (true) {
 System.out.println("请您输入需要购买电影名称:");
 String movieName = userInfo.nextLine();
 // 去当前商家下,查询该电影对象。
 Movie movie = getMovieByShopAndName(business, movieName);
 if (movie != null) {
     // 开始购买
while (true) {
 System.out.println("请您输入要购买的电影票数:");
 String number = userInfo.nextLine();
 int buyNumber = Integer.valueOf(number);
 // 判断电影是否购票
 if (movie.getNumber() >= buyNumber) {
     // 可以购买了
     // 当前需要花费的金额
     double money = BigDecimal.valueOf(movie.getPrice()).multiply(BigDecimal.valueOf(buyNumber))
             .doubleValue();
     if (loginUser.getMoney() >= money) {
         // 终于可以买票了
         System.out.println("您成功购买了" + movie.getName() + buyNumber +
                 "张票!总金额是:" + money);
         // 更新自己的金额 更新商家的金额
         loginUser.setMoney(loginUser.getMoney() - money);
         business.setMoney(business.getMoney() + money);
         movie.setNumber(movie.getNumber() - buyNumber);

         Customer c = (Customer) loginUser;
         // 记录购买电影的信息
         // 第一个参数是购买的电影,第二个参数是没有评价的标记!
         c.getBuyMovies().put(movie.getName(), false);
         return;
     } else {
         System.out.println("是否继续~~");
         System.out.println("是否继续买票?y/n");
         String command = userInfo.nextLine();
         switch (command) {
             case "y":
                 break;
             default:
                 System.out.println("好的!");
                 return;
         }
     }
 } else {
     // 票数不够
     System.out.println("您当前最多可以购买:" + movie.getNumber());
     System.out.println("是否继续买票?y/n");
     String command = userInfo.nextLine();
     switch (command) {
         case "y":
             break;
         default:
             System.out.println("OK");
             return;
                     }
                 }
             }

         } else {
             System.out.println("查无此片");
         }
     }
 } else {
     System.out.println("该电影院关门了~~~");
     System.out.println("是否继续买票?y/n");
     String command = userInfo.nextLine();
     switch (command) {
         case "y":
             break;
         default:
             System.out.println("OK");
             return;
          }
       }
    }
 }
}

4.2查看排片

    private static void showAllMovies() {
        System.out.println("=============展示全部商家排片信息=================");
        allMovies.forEach((business, movies) -> {
            System.out.println(business.getShopName() + "\t\t电话:" + business.getPhone() + "\t\t地址:" + business.getAddress());
            System.out.println("\t\t\t片名\t\t\t主演\t\t时长\t\t评分\t\t票价\t\t余票数量\t\t放映时间");
            for (Movie movie : movies) {
                System.out.println("\t\t\t" + movie.getName()+"\t\t\t" + movie.getActor()+ "\t\t" + movie.getTime()
                        + "\t\t" + movie.getScore() + "\t\t" + movie.getPrice() + "\t\t" + movie.getNumber() + "\t\t"
                        +   sdf.format(movie.getStartTime()));
            }
        });
    }

跟着写完突然开始怀疑人生,说实话我觉得用API很简单,难的是根据不同业务场景来用代码实现逻辑

相关文章
|
17天前
|
网络协议
keepalived对后端服务器的监测方式实战案例
关于使用keepalived进行后端服务器TCP监测的实战案例,包括配置文件的编辑和keepalived服务的重启,以确保配置生效。
29 1
keepalived对后端服务器的监测方式实战案例
|
22天前
|
资源调度 JavaScript 前端开发
TypeScript实战教程(一):表单上传与后端处理
本文是TypeScript实战教程的第一部分,介绍了使用TypeScript进行表单上传和后端处理的完整流程,包括环境配置、前端表单创建、使用TypeScript和Express框架搭建服务端、处理表单数据,并提供了详细的代码示例和运行测试方法。
TypeScript实战教程(一):表单上传与后端处理
|
28天前
|
存储 缓存 移动开发
不来看一看HTML请求后端性能优化的实战总结吗?
本文主要总结了在ICBU的核心沟通场景下服务端在此次性能优化过程中做的工作,供大家参考讨论。
|
1月前
|
存储 缓存 JavaScript
构建高效后端服务:Node.js与Express框架的实战应用
【8月更文挑战第2天】在数字化时代的浪潮中,后端服务的构建成为了软件开发的核心。本文将深入探讨如何利用Node.js和Express框架搭建一个高效、可扩展的后端服务。我们将通过实际代码示例,展示从零开始创建一个RESTful API的全过程,包括路由设置、中间件使用以及数据库连接等关键步骤。此外,文章还将触及性能优化和安全性考量,旨在为读者提供一套完整的后端开发解决方案。让我们一同走进Node.js和Express的世界,探索它们如何助力现代Web应用的开发。
|
19天前
|
大数据 数据处理 分布式计算
JSF 逆袭大数据江湖!看前端框架如何挑战数据处理极限?揭秘这场技术与勇气的较量!
【8月更文挑战第31天】在信息爆炸时代,大数据已成为企业和政府决策的关键。JavaServer Faces(JSF)作为标准的 Java Web 框架,如何与大数据技术结合,高效处理大规模数据集?本文探讨大数据的挑战与机遇,介绍 JSF 与 Hadoop、Apache Spark 等技术的融合,展示其实现高效数据存储和处理的潜力,并提供示例代码,助您构建强大的大数据系统。
25 0
|
20天前
|
JavaScript 安全 数据安全/隐私保护
深入Node.js与Express:从表单接收到数据验证的完整指南——实战技巧揭秘后端开发中的表单处理流程
【8月更文挑战第31天】在Web开发中,处理表单数据至关重要。本文通过实例详细讲解了如何利用Node.js与Express框架接收和验证表单数据。首先,搭建环境并初始化一个简单的Express应用;接着,演示如何接收用户注册表单中的`username`和`email`字段;最后,引入`joi`模块进行数据验证,确保数据安全准确。掌握这些技能有助于开发者构建更安全、友好的Web应用。随着Node.js和Express的不断进步,未来将有更多高级功能值得期待。
28 0
|
20天前
|
缓存 API 数据库
打造高性能后端API:从设计到部署的实战之旅
【8月更文挑战第31天】在数字化时代的浪潮中,后端API成为了连接用户、数据与服务的桥梁。本文将带领读者踏上一段从API设计、开发到部署的旅程,通过实际案例分析,揭示如何构建一个高性能的后端系统。我们将探讨现代后端架构的关键要素,包括RESTful API设计原则、数据库优化技巧、缓存策略、以及容器化部署的实践。文章旨在为开发者提供一套实用的方法论,帮助他们在面对复杂业务需求时,能够设计出既高效又可扩展的后端服务。
|
20天前
|
存储 NoSQL 关系型数据库
探索后端开发:从基础到进阶的实战之旅
【8月更文挑战第31天】在数字化时代的浪潮中,后端开发作为技术架构的核心,承载着数据处理和业务逻辑的重要任务。本文将带你走进后端开发的奇妙世界,通过深入浅出的方式,解析后端开发的基础知识、关键技术点以及进阶技巧。我们将一起动手实现一个简单的后端项目,体验从零开始构建一个服务端应用的过程。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你打开一扇通往后端世界的大门。
|
2月前
|
存储 开发框架 前端开发
循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合
循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合
|
1月前
|
JavaScript 前端开发 中间件
打造卓越后端:构建高效API的最佳实践与实战代码示例——解锁高性能Web服务的秘密
【8月更文挑战第2天】构建高效后端API:最佳实践与代码示例
56 0

热门文章

最新文章