三层架构——ATM + 购物车
三层架构:用户视图层、逻辑接口层、数据处理层。
一个功能,分成三层架构写,增加程序的可扩展性。
三层是互有联系的,从用户视图层开始写,涉及到那一层就到下一层去写,然后return 返回值,再写回来。
最关键的还是,要知道三层中的各个的职责是什么,那些代码写在哪一层,参数要传什么,返回值需要返回什么有用的信息,有利于本层的处理或输出,需要导入别的模块,互相导要‘雕花’。
用户视图层的接口和逻辑接口层的接口,主要功能是一一对应的,只不过,用户视图层是用户可以输入内容,看到结果,核心逻辑还是逻辑接口层内部需要处理的。
注意:用户视图层,逻辑接口层,数据处理层,都可以有多个,让代码结构更清晰,比如,用户视图层可以分为:用户视图层,管理员视图层;逻辑接口层可以分为:用户接口,商城接口,银行接口;等
用户视图层
from interface import user_interface,shop_interface,bank_interface
from db import db_handler
from lib import common
# 初始化的用户登录状态,登录用户名(全局变量)
login = False
user_in = None
# 1、注册功能
def register():
user = input('请输入账号:').strip()
pwd = input('请输入密码:').strip()
pwd1 = input('请确认密码:').strip()
if user:
if pwd:
if pwd == pwd1:
users = user_interface.register_interface(user,pwd)
print(users)
return user
else:
print('密码不一致')
else:
print('密码不能为空哦')
else:
print('账号不能为空哦')
# 2、登录功能
def user_login():
global login
global user_in
while True:
user = input('请输入账号:').strip()
pwd = input('请输入密码:').strip()
login, user_in = user_interface.login_interface(user,pwd)
if login:
print('登录成功')
break
else:
print(user_in)
# 3、查看余额
@common.check_login
def look_money():
money = bank_interface.look_money_interface(user_in)
print('用户 {} 余额为:{}'.format(user_in,money))
# 4、提现功能
@common.check_login
def top_up():
while True:
money = input('请输入提现金额:').strip()
if money.isdigit():
done, result = bank_interface.top_up_interface(money,user_in)
print(result)
break
else:
print('请输入整数数字')
# 5、还款功能
@common.check_login
def repay():
while True:
money = input('请输入充值金额:').strip()
if money.isdigit():
result = bank_interface.repay_money_interface(user_in,money)
print(result)
break
else:
print('请输入整数金额')
# 6、转账功能
@common.check_login
def transfer():
while True:
user2 = input('你想转给谁:').strip()
money = input('你想转多少:')
if money.isdigit():
done, result = bank_interface.transfer_interface(user_in,user2,money)
print(result)
if done:
break
else:
print('请输入整数金额')
# 7、查看流水
@common.check_login
def look_flow():
flow = bank_interface.look_flow_interface(user_in)
if flow:
print('流水为:{}'.format(flow))
else:
print('no flow')
# 8、购物功能
@common.check_login
def shopping():
while True:
print('商品列表如下哦:')
shop_dic = db_handler.get_shop_data()
for i in range(len(shop_dic)):
print('{} {} {} 元'.format(i,shop_dic[str(i)][0],shop_dic[str(i)][1]))
choice = input('请输入编号,q 退出:').strip()
if choice.lower() == 'q':
break
if choice in shop_dic:
result = shop_interface.in_shop_interface(user_in,shop_dic[choice])
print(result)
else:
print('没有这个编号的商品')
# 9、查看购物车
@common.check_login
def look_shop_car():
result_shop = shop_interface.look_shop_interface(user_in)
goods = result_shop[1]
if result_shop[0] != 0:
print('购物车商品如下:')
for good in goods:
print('商品名称:{} 商品数量:{} 商品单价:{} 元 '.format(good,goods[good][0],goods[good][1]))
print('商品总价格:{}'.format(result_shop[0]))
choice = input('是否付款:y/n:').strip()
if choice.lower() == 'y':
result = bank_interface.pay_money_interface(user_in)
print(result[1])
else:
print('还没有商品')
# 10、管理员视图层
@common.check_login
def rooter():
from core import root # 涉及到循环导入,从这里调用管理员视图层,管理员视图层也需要该用户视图层的信息,比如,已登录的账号名,登录状态(全局变量)
root.root_run() # 新的管理员的视图层
def run():
func_dic = {
'0': ['用户注册', register],
'1': ['用户登录', user_login],
'2': ['查看余额', look_money],
'3': ['提现', top_up],
'4': ['还款', repay],
'5': ['转账', transfer],
'6': ['查看流水', look_flow],
'7': ['购物', shopping],
'8': ['查看购物车', look_shop_car],
'9': ['管理员', rooter],
}
# settings.logging.info('egon充值5元') #Windows 存储 gbk mac Linux 存储 utf-8
while True:
print('功能列表如下:')
for i in range(len(func_dic)):
print('{} {}'.format(i,func_dic[str(i)][0]))
choice = input('请输入编号(q退出):').strip()
if choice.lower() == 'q':
break
if choice in func_dic:
func_dic[choice][1]()
else:
print('没有这个功能编号,傻叉')
以下功能主要是逻辑接口层的代码,没有模块的引用,你应该都会
注意:流水记录在用户信息中,日志用配置文件的logging设置,common:加密密码接口,登录认证装饰器
注册功能:
用户视图层:输入用户名和密码,确认密码,进行小逻辑判断,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即用户名,密码。调用查看用户接口(数据处理层),进行注册功能的核心逻辑处理,判断用户是否存在,不存在就添加用户,将处理结果返回给用户视图层。逻辑处理过程中,涉及到数据处理,要将一些值交给数据处理层,处理后的结果继续使用,或者返回用户视图层。
数据处理层:接收其它层的数据,进行数据的增删改查,是数据相关的一些操作。注册:查:查询用户接口,返回用户信息,如果返回信息不为空,就是存在该用户,返回None,就是不存在该用户,查询用户接口是与数据处理相关,所以是数据处理层;增改:更新用户数据接口,增加该用户,也可以看做是修改用户的存储信息。
# 注册接口
def register_interface(user, pwd):
user_data = db_handler.check_user(user)
if user_data:
return '用户已存在'
pwd = common.get_mb5_pwd(pwd)
user_dic = {
'username': user,
'pwd': pwd,
'flow': [],
'shop': {},
'balance': 0,
'block': False
}
settings.logging.info('{} 注册了'.format(user))
db_handler.add_user(user_dic)
return '注册成功'
登录功能:
用户视图层:输入用户名和密码,进行小逻辑判断,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即用户名,密码。进行核心逻辑处理,判断用户是否存在,存在就校验密码是否正确,如果正确,就登录成功,将处理结果返回给用户视图层。逻辑处理过程中,涉及到数据处理,要将一些值交给数据处理层,处理后的结果继续使用,或者返回用户视图层。可以从数据处理层返回的信息中,得到用户名和密码,进行校验。
数据处理层:接收其它层的数据,进行数据的增删改查,是数据相关的一些操作。登录:查:返回用户信息;
# 登录接口
def login_interface(user, pwd):
user_dic = db_handler.check_user(user)
if user_dic:
if user_dic['block']:
return False, '用户已被锁定了'
pwd = common.get_mb5_pwd(pwd)
if pwd == user_dic.get('pwd'):
user_in = user
settings.logging.info('{} 登录了'.format(user))
return True, user_in
else:
return False, '密码不正确'
else:
return False, '用户不存在'
注意:密码要进行加密操作,用户信息字典,要存储成json格式。
以下功能要注意验证登录状态,即添加登录装饰器,登录后才能操作,设置全局变量登录状态:login,登录用户user_in
查看余额:
用户视图层:将登录用户名传给查看用户接口,即传到逻辑接口层,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即已登录用户名。进行核心逻辑处理,因为是已登录用户,所以,不用判断用户是否存在;调用数据处理的查询用户接口,直接将用户名传到数据处理层,将处理结果,即用户信息字典,得到字典后,可以 得到 该用户的余额,将其返回给用户视图层打印。
数据处理层:接收其它层的数据,进行数据的增删改查,是数据相关的一些操作。查询余额:查:返回用户信息;
# 查询余额接口
def look_money_interface(user):
user_dic = db_handler.check_user(user) # 查看用户接口
money = user_dic.get('balance')
return money
提现:
用户视图层:将登录用户名传给查看用户接口,即传到逻辑接口层,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即已登录用户名。进行核心逻辑处理,调用数据处理的查询用户接口,直接将用户名传到数据处理层,将处理结果,即用户信息字典,得到字典后,可以 修改 用户的余额,再将修改后的用户信息,调用 数据层 的 数据更新接口 ,将用户信息进行重新写入,将其结果,比如说,'提现成功',返回给用户视图层打印。
数据处理层:接收其它层的数据,进行数据的增删改查,是数据相关的一些操作。提现:查:查询用户接口,返回用户信息;改:更新用户接口,将用户新的信息重新写入文件,注意:在'w'模式下,没有文件,就创建文件。所以,更新数据,和注册账号,都可以用这个接口。并且,重新写入,也是利用了'w'模式的打开文件,先将文件清空,再写入的方式。
# 提现功能接口
def top_up_interface(money, user):
user_dic = db_handler.check_user(user)
money = float(money)
if money * 1.05 > user_dic.get('balance'):
settings.logging.info('{} 提现失败'.format(user))
return False, '提现失败,余额不足'
user_dic['balance'] = float(user_dic.get('balance')) - money * 1.05
user_dic['flow'].append('{} {} 提现了 {} 元'.format(time.strftime('%Y-%m-%d %X'), user, money))
db_handler.update_user(user_dic)
settings.logging.info('{} 提现成功,金额为:{} 元'.format(user,money))
return True, '提现成功,金额为:{} 元,余额为:{} , 手续费:{} 元'.format(money, user_dic['balance'], money * 0.05)
还款:
用户视图层:将登录用户名传给查看用户接口,即传到逻辑接口层,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即已登录用户名。进行核心逻辑处理,调用数据处理的查询用户接口,直接将用户名传到数据处理层,将处理结果,即用户信息字典,得到字典后,还款,即将金额进行充值,增加金额,将新的用户信息,通过数据处理层的更新用户信息的接口,重新写入用户信息,将其结果,比如说 True,'还款成功,金额为:...'。返回给用户视图层打印。
数据处理层:接收其它层的数据,进行数据的增删改查,是数据相关的一些操作。查询余额:查:返回用户信息,查询用户接口;改:更新用户数据信息,更新用户信息接口
# 还款功能接口
def repay_money_interface(user, money):
money = float(money)
user_dic = db_handler.check_user(user)
user_dic['balance'] = float(user_dic['balance'] + money)
user_dic['flow'].append('{} {} 还款 {} 元'.format(time.strftime('%Y-%m-%d %X'), user, money))
db_handler.update_user(user_dic)
settings.logging.info('{} 还款,金额为:{} 元'.format(user,money))
return '还款成功,金额为:{}'.format(money)
转账:
用户视图层:将登录用户名,目标用户,转账金额,传给查看用户接口,即传到逻辑接口层,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即已登录用户名,目标账户,转账金额。调用查看数据处理层的查看用户接口,得到用户信息,判断已登录账户钱够不够,够的话,就减少转账用户的金额,将信息更新,调用更新用户信息接口;把目标用户也取出来,进行数据更新。将处理结果返回给用户视图层。
数据处理层:转账:查:查看用户信息接口,返回用户信息,即转账用户,目标用户的用户信息,都要进行处理;改:更新用户数据信息,更新用户信息接口,更新两个用户的信息
# 转账功能接口
def transfer_interface(user, user2, money):
user_dic2 = db_handler.check_user(user2)
if not user_dic2:
return False, '没有这个用户哦'
user_dic = db_handler.check_user(user)
if float(user_dic.get('balance')) > float(money):
user_dic['balance'] = float(user_dic['balance']) - float(money)
user_dic['flow'].append('{} {} 转账给 {} {} 元'.format(time.strftime('%Y-%m-%d %X'), user, user2, money))
db_handler.update_user(user_dic)
user_dic2['balance'] = float(user_dic2['balance']) + float(money)
user_dic2['flow'].append('{} {} 收到 {} 转账 {} 元'.format(time.strftime('%Y-%m-%d %X'), user2, user, money))
db_handler.update_user(user_dic2)
settings.logging.info('{} 转账给 {} ,金额:{} 元'.format(user,user2,money))
return True, '转账成功,金额为:{}'.format(money)
else:
user_dic['flow'].append('{} {} 转账给 {} {} 元,失败!'.format(time.strftime('%Y-%m-%d %X'), user,user2,money))
settings.logging.info('{} 转账给 {} ,失败!'.format(user,user2))
return False, '转账失败,金额不足'
查看流水:
用户视图层:将登录用户名,传给查看用户接口,即传到逻辑接口层,接收逻辑接口层的返回值,打印输出结果。
逻辑处理层:接收用户视图层的输入,即已登录用户名。调用查看用户接口,得到用户信息,返回流水,用户视图层
数据处理层:查看流水:查:返回用户信息,查询用户接口;
# 查看流水接口
def look_flow_interface(user):
user_dict = db_handler.check_user(user)
return user_dict['flow']
购物:
用户视图层:将用户选择的编号传给,逻辑接口层。
逻辑处理层:接收用户视图层的输入的编号。将商品加入购物车,即调用查看用户接口(数据处理层),得到用户信息字典,将商品信息加入到用户字典的购物车信息里,比如,商品名称,单价,数量。
数据处理层:更新用户信息字典。
# 加入购物车接口
def in_shop_interface(user,list_shop):
user_dic = db_handler.check_user(user)
if list_shop[0] not in user_dic['shop']:
user_dic['shop'][list_shop[0]] = [1,list_shop[1]]
else:
user_dic['shop'][list_shop[0]][0] = int(user_dic['shop'][list_shop[0]][0]) + 1
db_handler.update_user(user_dic)
settings.logging.info('{} 购买了 {}'.format(user,list_shop[0]))
return '已加入购物车,商品为:{} , 价格:{} 元'.format(list_shop[0],list_shop[1])
查看购物车:
用户视图层:将已登录用户名传给逻辑接口层。得到购物车信息,打印。然后询问是否结算,如果结算,调用支付接口(逻辑接口层),
逻辑处理层:调用查看用户接口(数据处理层),得到用户信息字典,将购物车信息返回给用户视图层;支付接口:判断金额够不够,够的话就,减少金额,清空购物车,即把用户信息字典的购物车赋值为空,比如空字典。更新用户信息接口(数据处理层),更新用户数据。
数据处理层:查看用户接口,更新用户数字接口
# 查看购物车接口
def look_shop_interface(user):
user_dic = db_handler.check_user(user)
goods = user_dic['shop']
money_sum = 0
for i in goods:
money_sum += float(goods[i][0]) * int(goods[i][1])
return money_sum, goods
# 结算支付接口
def pay_money_interface(user):
user_dic = db_handler.check_user(user)
goods = user_dic['shop']
money_sum = 0
for i in goods:
money_sum += float(goods[i][0]) * int(goods[i][1])
if float(user_dic['balance']) > money_sum:
user_dic['balance'] = float(user_dic['balance']) - money_sum
user_dic['flow'].append('{} {} 付款成功,金额为: {} 元'.format(time.strftime('%Y-%m-%d %X'), user, money_sum))
user_dic['shop'] = {}
db_handler.update_user(user_dic)
settings.logging.info('{} 付款:{} 元'.format(user,money_sum))
return True, '付款成功,金额为:{}'.format(money_sum)
else:
settings.logging.info('{} 付款失败'.format(user))
return False, '付款失败,请充值'
管理员功能:
可以新建一个视图层,为管理员的视图层,按照三层架构去写每个功能。
# 检测是否是管理员,是的话就运行管理员视图层
def root_check_interface(user):
user_dic = db_handler.check_user(user)
if user_dic.get('root'):
return True
数据处理层
from conf import settings
import os
import json
def check_user(username): # 查看用户接口
file_path = os.path.join(settings.USER_DATA_PATH, '{}.json'.format(username))
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
dic = json.load(f)
return dic
def update_user(dic): # 数据更新接口
dic_path = os.path.join(settings.USER_DATA_PATH,'{}.json'.format(dic['username']))
with open(dic_path,'w',encoding='utf-8') as f:
json.dump(dic,f)
add_user = update_user #写了两个一样的数据更新程序,所以去掉一个,赋值给add_user
def get_shop_data(): # 获得商品信息接口,从文件中获得
with open(settings.SHOP_DATA_PATH,'r',encoding='utf-8') as f:
return json.load(f)
三层架构——ATM + 购物车的更多相关文章
- ATM购物车+三层结构项目设计
ATM购物车项目 模拟实现一个ATM + 购物商城程序. 该程序实现普通用户的登录注册.提现充值还款等功能,并且支持到网上商城购物的功能. 账户余额足够支付商品价格时,扣款支付:余额不足时,无法支付, ...
- MVC项目实践,在三层架构下实现SportsStore-06,实现购物车
SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...
- java:Session(概述,三层架构实例(实现接口封装JDBC),Session实现简单购物车实例)
1.Session概述: Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 Web 页之间跳转时,存 ...
- python以ATM+购物车剖析一个项目的由来及流程
ATM+购物车 一个项目是如何从无到有的 ''' 项目的由来,几个阶段 0.采集项目需求 1.需求分析 2.程序的架构设计 3.分任务开发 4.测试 5.上线运行 ''' 需求分析: # 对项目需求进 ...
- 阶段性项目 ATM+购物车项目
ATM + 购物车https://www.cnblogs.com/kermitjam/articles/10687180.html readme 内容前戏: 一个项目是如何从无到有的. 一 需求分析 ...
- 浅析MVC模式与三层架构的区别01
三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层)三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI ...
- MVC项目实践,在三层架构下实现SportsStore,从类图看三层架构
在"MVC项目实践,在三层架构下实现SportsStore-02,DbSession层.BLL层"一文的评论中,博友浪花一朵朵建议用类图来理解本项目的三层架构.于是就有了本篇: I ...
- MVC模式与三层架构的区别
之前总是混淆MVC表现模式和三层架构模式,为此记录下. 三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层) 三层架构(3-tier application) ...
- MVC项目实践,在三层架构下实现SportsStore-02,DbSession层、BLL层
SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...
随机推荐
- USB小白学习之路(1) Cypress固件架构解析
Cypress固件架构彻底解析及USB枚举 1. RAM的区别 56pin或者100pin的cy7c68013A,只有内部RAM,不支持外部RAM 128pin的cy7c68013A在pin脚EA=0 ...
- SpringCloud入门(六): Hystrix监控
Hystrix.stream 监控 <!--. 配置pom文件,引入actuator包--> <dependency> <groupId>org.springfra ...
- go语言指南之切片练习
题目: 实现 Pic.它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片.当你运行此程序时,它会将每个整数解释为灰度值(好吧,其实是蓝度值)并显示它所对 ...
- SQL Server 最小日志记录
SQL Server之所以记录事务日志,首要目的是为了把失败或取消的操作还原到最原始的状态,但是,并不是所有的操作都需要完全记录事务日志,比如,在一个空表上放置排他锁,把大量的数据插入到该空表中.即使 ...
- Flink消费Kafka到HDFS实现及详解
1.概述 最近有同学留言咨询,Flink消费Kafka的一些问题,今天笔者将用一个小案例来为大家介绍如何将Kafka中的数据,通过Flink任务来消费并存储到HDFS上. 2.内容 这里举个消费Kaf ...
- C语言程序设计(九) 指针
第九章 指针 C程序中的变量都是存储在计算机内存特定的存储单元中的,内存中的每个单元都有唯一的地址 通过取地址运算符&可以获得变量的地址 //L9-1 #include <stdio.h ...
- button控件根据文本自适应
2020-03-12 每日一例第5天 1.添加按钮1和label.textbox控件,并修改相应的text值: 2.修改textBox1的TextChanged事件并输入代码: button1.Tex ...
- 常见的几种JavaScript内存泄露
总结一下常见的几种JavaScript内存泄露: 1.意外的全局变量 全局变量属于window对象,所以只会随着window销毁才会销毁. 2.console.log() conaole.log()函 ...
- 深入理解计算机系统 (CS:APP) 缓冲区漏洞实验 – Buffer Lab 解析
原文地址:https://billc.io/2019/05/csapp-cachelab/ 写在前面 这是 CSAPP 官网上的第 4 个实验 buflab,也是学校要求的第三个实验.这个实验比上一个 ...
- Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)
Airport Simulation 是数据结构与算法教材中用于演示Queue的一个小程序(大多数教师似乎会跳过这个练习).主程序会通过输入总的运行时间.队列里可以等待的最多飞机数量,平均每个时间单元 ...