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

简介: 面向对象实战训练

@TOC

前言

这是老师带着敲的项目,主要锻炼面向对象思想的实现,针对不同场景应该用什么样的集合容器来存储数据,什么时候该用泛型,什么时候该用分支控制语句,什么时候要避免使用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很简单,难的是根据不同业务场景来用代码实现逻辑

相关文章
|
2月前
|
缓存 前端开发 Go
从4开始,在后端系统中增加用户注册和登录功能
从4开始,在后端系统中增加用户注册和登录功能
21 0
|
1月前
|
存储 缓存 监控
微信团队分享:微信后端海量数据查询从1000ms降到100ms的技术实践
针对大数据量带来的查询性能问题,微信团队对数据层查询接口进行了针对性的优化,将平均查询速度从1000ms+优化到了100ms级别。本文为各位分享优化过程,希望对你有用!
32 2
|
3月前
|
JSON Java 数据库
基于uniapp原生组件uni-ui 做一个登录注册与个人中心(后端篇)
基于uniapp原生组件uni-ui 做一个登录注册与个人中心(后端篇)
108 2
|
3月前
|
前端开发 数据安全/隐私保护
uniapp-含有后端的登录注册页面编写(二)
uniapp-含有后端的登录注册页面编写(二)
69 0
|
3月前
|
存储 SQL 安全
uniapp-含有后端的登录注册页面编写(一)
uniapp-含有后端的登录注册页面编写
113 0
|
17天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
19天前
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
32 0
|
1月前
|
JSON 前端开发 Java
layui上传图片,前端直接拷代码,后端……
layui上传图片,前端直接拷代码,后端……
29 0
|
1月前
|
前端开发
前端接受后端文件流并下载到本地的方法
前端接受后端文件流并下载到本地的方法
60 0
|
1月前
|
存储 前端开发 JavaScript
从前端到后端,探索现代Web开发技术
本文探索了现代Web开发技术的各个方面,包括前端和后端开发以及多种编程语言的应用。通过对JavaScript、Java、Python、C、PHP和Go等语言的介绍,深入探讨了前端和后端开发的基本原理和常用工具。同时,还涵盖了数据库技术在Web开发中的重要性和应用场景。无论你是初学者还是有经验的开发者,本文都能为你提供全面的视角和实用的知识,帮助你在Web开发领域取得更好的成果。