【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很简单,难的是根据不同业务场景来用代码实现逻辑

相关文章
|
7天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
43 4
|
8天前
|
小程序 前端开发 算法
|
10天前
|
JavaScript API 开发工具
<大厂实战场景> ~ Flutter&鸿蒙next 解析后端返回的 HTML 数据详解
本文介绍了如何在 Flutter 中解析后端返回的 HTML 数据。首先解释了 HTML 解析的概念,然后详细介绍了使用 `http` 和 `html` 库的步骤,包括添加依赖、获取 HTML 数据、解析 HTML 内容和在 Flutter UI 中显示解析结果。通过具体的代码示例,展示了如何从 URL 获取 HTML 并提取特定信息,如链接列表。希望本文能帮助你在 Flutter 应用中更好地处理 HTML 数据。
93 1
|
10天前
|
JSON Dart 数据格式
<大厂实战场景> ~ flutter&鸿蒙next处理后端返回来的数据的转义问题
在 Flutter 应用开发中,处理后端返回的数据是常见任务,尤其涉及转义字符时。本文详细探讨了如何使用 Dart 的 `dart:convert` 库解析包含转义字符的 JSON 数据,并提供了示例代码和常见问题的解决方案,帮助开发者有效处理数据转义问题。
105 0
|
11天前
|
前端开发 JavaScript NoSQL
探索后端开发之旅:从基础到高级实战
【10月更文挑战第24天】在这个数字时代的浪潮中,后端开发如同一座巨大的宝藏岛,等待着勇敢的探险者去发掘。本文将作为你的藏宝图,引领你从浅滩走向深海,探索后端开发的广阔天地。无论你是初心者还是资深开发者,这篇文章都将为你提供价值连城的知识和技能。准备好了吗?让我们启航,一起构建强大、高效、安全的后端系统!
|
2月前
|
网络协议
keepalived对后端服务器的监测方式实战案例
关于使用keepalived进行后端服务器TCP监测的实战案例,包括配置文件的编辑和keepalived服务的重启,以确保配置生效。
54 1
keepalived对后端服务器的监测方式实战案例
|
3月前
|
大数据 数据处理 分布式计算
JSF 逆袭大数据江湖!看前端框架如何挑战数据处理极限?揭秘这场技术与勇气的较量!
【8月更文挑战第31天】在信息爆炸时代,大数据已成为企业和政府决策的关键。JavaServer Faces(JSF)作为标准的 Java Web 框架,如何与大数据技术结合,高效处理大规模数据集?本文探讨大数据的挑战与机遇,介绍 JSF 与 Hadoop、Apache Spark 等技术的融合,展示其实现高效数据存储和处理的潜力,并提供示例代码,助您构建强大的大数据系统。
45 0
|
6天前
|
API 持续交付 开发者
后端开发中的微服务架构实践与挑战
在数字化时代,后端服务的构建和管理变得日益复杂。本文将深入探讨微服务架构在后端开发中的应用,分析其在提高系统可扩展性、灵活性和可维护性方面的优势,同时讨论实施微服务时面临的挑战,如服务拆分、数据一致性和部署复杂性等。通过实际案例分析,本文旨在为开发者提供微服务架构的实用见解和解决策略。
|
4天前
|
Web App开发 存储 JavaScript
深入浅出Node.js后端开发
【10月更文挑战第31天】本文将引导你进入Node.js的奇妙世界,探索其如何革新后端开发。通过浅显易懂的语言和实际代码示例,我们将一起学习Node.js的核心概念、搭建开发环境,以及实现一个简单但完整的Web应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇通往高效后端开发的大门。
|
2天前
|
消息中间件 设计模式 运维
后端开发中的微服务架构实践与挑战####
本文深入探讨了微服务架构在现代后端开发中的应用,通过实际案例分析,揭示了其在提升系统灵活性、可扩展性及促进技术创新方面的显著优势。同时,文章也未回避微服务实施过程中面临的挑战,如服务间通信复杂性、数据一致性保障及部署运维难度增加等问题,并基于实践经验提出了一系列应对策略,为开发者在构建高效、稳定的微服务平台时提供有价值的参考。 ####