Jam*_*new 11 php shopping-cart class-design
我有一个应用程序,它本质上是第三方API的包装器.该应用程序不使用数据库,只存储单个cookie,这是API所需的会话ID.
API是一个允许用户使用的购物系统
-login/register/edit profile/logout
- 买的商品
-做捐献
-成为会员
API有50个左右的方法,我的应用程序需要连接到这些方法.示例API调用是addItemToBasket(),addDonation(),GetUserDetails()等.
我试图弄清楚我的应用程序中应该是什么类.这是我到目前为止:
类
1)APIManager()类 包含与第三方API中公开的方法一对一匹配的方法,并提供与远程API服务器建立连接的机制.因此用户将通过登录
APIManager->loginUser($sessionKey, $uid, $pwd);
Run Code Online (Sandbox Code Playgroud)
并且远程API会将用户设置为已登录.如果需要,我的应用程序可以通过调用API来检查任何会话密钥的登录状态:
APIManager->isLoggedIn($sessionKey);
Run Code Online (Sandbox Code Playgroud)
2)User()类 这包含在处理API调用(如Register或Login)之前包含所需业务逻辑的方法.一个示例方法是:
function login($_POST) {
//perform sanity checks, apply business rules etc.
//if certain conditions are met, we may pass in a promo code, $pc
APIManager->loginUser($sessionkey, $_POST['uid'], $_POST['pwd'], $pc);
}
Run Code Online (Sandbox Code Playgroud)
我意识到我可能只是从登录页面调用APIManager,而不是拥有User类本身,但我觉得因为在我们实际调用API的loginUser()方法之前需要运行一些业务逻辑,所以感觉有权在User类中处理.我很想知道人们对此的看法.
3)篮子()类
篮子是在第三方API中管理的,所以我的应用程序的作用是进行适当的API调用以将新项目添加到购物篮,删除项目,查看购物篮等.我的应用程序对篮子一无所知,直到从中检索数据API,也不能通过API进行任何更改.同样,将这种相关逻辑分组到Basket类中是合适的.前端网页可能会调用以下内容:
Basket->addItem(23);
Run Code Online (Sandbox Code Playgroud)
而这个Basket类中的addItem()方法看起来像:
addItem($itemID) {
//perform checks, apply business rules e.g. if user is eligible for discount
APIManager->addToCart($itemID, $discount);
}
Run Code Online (Sandbox Code Playgroud)
其中addToCart()是我们调用来处理项目的第三方API方法.
4)捐赠()类
这允许用户进行捐赠.捐赠出现在篮子里,可以从篮子里取出.我想到只是在Basket类中添加一个addDonate()方法而不用担心有Donation对象,但是......(见下文)
5)会员资格()类
...会员资格实际上是一种捐赠!该API将捐赠进入某个帐户作为1年会员资格,而不是简单的捐赠.我们无法更改第三方API的逻辑/行为.
因此,如果我向帐户"1"捐赠50美元,那么这只是一次正常的捐赠,但如果我向帐户"8"捐赠100美元,那么我就会成为所有会员福利的成员(降价,没有邮费等).
在这里,我不确定设计这个的最佳方式.
我应该创建一个捐赠类,然后使用成员资格扩展它,因为成员资格将需要所有捐赠方法.但会员资格需要其他方法,如renew()或getExpiry()等.
另外,我应该考虑扩展用户成为会员吗?同样,成员拥有User拥有的所有核心方法,但还有其他成员,例如只有成员才能访问的getSpecialOffers()或getDiscountCode().
任何有关如何最好地接近设计的指导都将非常感激.
谢谢,詹姆斯
irc*_*ell 23
就个人而言,我会在3层中构建它.
第1层: API接口
此层是发生对远程API的实际行级别调用的位置.这一层都是关于协议的.此层中应该没有任何特定于API的内容.一切都应该是100%通用的,但应该能够被中间层用于与API交互.请注意,此层可以来自库或其他来源,如框架.或者你可以自定义.这一切都取决于你的位置和你的确切需求.
一些可能属于这里的类:
第2层: API适配器
该层实际上具有硬编码的API信息.这基本上是适配器模式.基本上,该层的工作是使用Interface层将远程API转换为本地API.因此,根据您的需要,您可以以1:1的方式镜像远程API,或者您可以根据需要稍微改变一下.但要记住的是,本课程不是为您的程序提供功能.目的是将远程API与本地代码分离.通过交换此类,您的代码应该能够快速适应使用不同版本的远程API,甚至可能使用不同的远程API.
需要记住的一件重要事情是,此适配器层旨在包含API.因此,每个类的范围都是API实现的全部内容.因此适配器和远程API之间应该有1:1的映射.
可能在这里的一些类:
第3层:内部对象
此图层应该是您对不同对象的内部表示(在您的特定情况下:用户,购物篮,购物车,捐赠,会员等).他们不应该直接调用API,但使用的组合物(依赖注入)成为什么基本上是一个桥梁的API.通过保持它分离,您应该能够完全独立于内部类来改变API(反之亦然).
所以,你的一个类看起来像这样:
class User {
protected $api;
public function __construct(iAPIAdapter $api) {
$this->api = $api;
}
public function login() {
$this->api->loginUser($blah);
}
}
Run Code Online (Sandbox Code Playgroud)
这样,就没有真正需要API 管理器的话.只需在程序开始时创建API的新实例,并将其传递给代码的其余部分.但它的主要优点是非常灵活,因为您应该能够通过简单地在代码中交换适配器层(当您实例化适配器时)来更改API(版本或调用本身).其他一切都应该正常工作,你应该完全与你的代码或远程API的更改隔离(更不用说如果以这种方式构建它应该是非常可测试的)...
这是我的0.02美元.这可能有点矫枉过正,但这真的取决于你的确切需要......