- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我目前有 4 种类型的用户,我们预计 future 至少会增加 3 种。目前他们是:
在不久的将来,我将不得不让这两名员工同时成为客户。我也会有支持中心和记者。
创作。创建。创建。我不担心访问控制、权限等......我现在拥有的代码可以在这方面创造奇迹。我的问题只是关于创作。似乎抽象工厂可能适合我,但事实是所有那些使用书籍和汽车教授设计模式的“抽象教程”并没有帮助我把它带到我的情况中。要么我使用了错误的设计模式,要么我不理解它。
在 UserFactory 类中,我们可以看到问题的根源:abstract public function signUp();
。这是一种不好的做法,甚至会导致 PHP 5.4+ 上的 Strict Standard 错误不遵守方法签名。在 Java 中,我会使用方法重载来解决这个问题。在 PHP 中,方法重载的工作方式不同,不允许我以这种方式工作。
<?php
abstract class UserFactory {
const ADMIN = 'AdminRecord';
const MANAGER = 'ManagerRecord';
const SALESMAN = 'SalesmanRecord';
const CUSTOMER = 'CustomerRecord';
public static function manufacture($type) {
return new $type;
}
protected $accountController;
protected $emailController;
protected $toolMailer;
function __construct() {
$this->accountController = new AccountController();
$this->emailController = new EmailController();
$this->toolMailer = new ToolMailer();
}
abstract public function signUp();
}
这是我的第一个用例:创建新管理员。
class AdminRecord extends UserFactory {
protected $accountCompanyController;
function __construct() {
parent::__construct();
$this->accountCompanyController = new AccountCompanyController();
}
public function signUp($name, $email, $password, $companyId, $access) {
$accountId = $this->accountController->add($name, $password);
$this->emailController->add($email, $accountId);
$this->accountCompanyController->add($accountId, $companyId, $access);
$this->toolMailer->adminWelcome($name, $email, $password);
}
}
在这里我创建了一个新的抽象类,因为我的两个用例属于同一个实体(销售员和经理都是具有不同访问级别的员工)。
abstract class StaffRecord extends UserFactory {
protected $staffController;
function __construct() {
parent::__construct();
$this->staffController = new staffController();
}
}
在这里,SignUp 的签名将与 Admin 相同,这排除了使用 func_num_args()
和 func_get_args()
的工作。等等,但是在 Java 中你不能使用方法重载来解决这个问题。没错,但在 Java 中,我可以将 int $shopId
替换为 Shop shop
并将 int $companyId
替换为 Company company
。
class ManagerRecord extends StaffRecord {
public function signUp($name, $email, $password, $shopId, $access) {
$accountId = $this->accountController->add($name, $password);
$this->emailController->add($email, $accountId);
$this->staffController->add($accountId, $shopId, $access);
$this->toolMailer->managerWelcome($name, $email, $password);
}
}
这里的 SignUp 方法与之前看到的两种情况都不同。
class SalesmanRecord extends StaffRecord {
public function signUp($name, $email, $password, $cpf, $shopId, $access) {
$accountId = $this->accountController->addSeller($name, $password, $cpf);
$this->emailController->add($email, $accountId);
$this->staffController->add($accountId, $shopId, $access);
$this->toolMailer->salesmanWelcome($name, $email, $password);
}
}
这里的 SignUp 方法与以前更加不同。
class CustomerRecord extends UserFactory {
protected $customerController;
function __construct() {
parent::__construct();
$this->customerController = customerController();
}
public function signUp($name, $email, $password, $cpf, $phone, $birthday, $gender) {
$accountId = $this->accountController->addCustomer($name, $password, $cpf, $phone, $birthday, $gender);
$this->emailController->add($email, $accountId);
$this->toolMailer->customerWelcome($name, $email, $password);
}
}
最佳答案
这是我的实现:
我利用 Interface to 使 signUp 函数为每种用户类型接受不同类型的参数;
接口(interface)创建:
namespace main;
interface UserInterface { }
您可以添加每个类需要实现的方法。现在,只需将其用作 signUp() 的类型提示对象;
通过在 signUp(User $user) 上使用类型提示,它将解决您在注册中传递的不同类型签名的问题。它可以是用户类型管理员、经理、销售员和客户。每个 {User}Record 都扩展并实现了抽象工厂,但在实现上有所不同。
我假设每种用户类型都有相应的/独特的行为。我添加了名为:AbstractUser.php、UserAdmin.php、UserManager.php、UserSalesman.php 和 UserCustomer.php 的额外类。每个类将包含不同类型的用户和属性,但扩展了一个抽象类用户,这对每个类都是通用的(电子邮件、姓名、密码);
AbstractUser.php - 我注意到一个用户的共同属性,所以我创建了一个抽象用户。公共(public)属性(电子邮件、姓名、密码)
<?php
namespace main;
abstract class AbstractUser {
public $email;
public $name;
public $password;
public function __construct($email, $name, $password) {
$this->email = $email;
$this->name = $name;
$this->password = $password;
}
}
让我们重写您的 UserFactory.php。但是这一次,它包含了我们作为 User 构建的 UserInterface.php 接口(interface);
namespace main;
use main\UserInterface as User;
abstract class UserFactory {
const ADMIN = 'AdminRecord';
const MANAGER = 'ManagerRecord';
const SALESMAN = 'SalesmanRecord';
const CUSTOMER = 'CustomerRecord';
public static function manufacture($type) {
return new $type;
}
protected $accountController;
protected $emailController;
protected $toolMailer;
function __construct() {
$this->accountController = new \stdClass();
$this->emailController = new \stdClass();
$this->toolMailer = new \stdClass();
}
abstract public function signUp(User $user);
}
注意方法 signUp();我用创建的界面提示它,这意味着它将只接受具有 User 实例的对象用户(实现用户界面)。
我假设下一组代码是不言自明的:
用户管理员:
<?php
namespace main;
use main\AbstractUser;
class UserAdmin extends AbstractUser implements UserInterface {
public $companyId;
public $access;
public function __construct($email, $name, $password, $companyId) {
parent::__construct($email, $name, $password);
$this->companyId = $companyId;
$this->access = UserFactory::ADMIN;
}
}
AdminRecord: signUp(User $user) 应该只接受 UserAdmin.php 的实例
<?php
namespace main;
use main\UserFactory;
use main\UserInterface as User;
class AdminRecord extends UserFactory {
protected $accountCompanyController;
function __construct() {
parent::__construct();
$this->accountCompanyController = new \stdClass(); //new AccountCompanyController();
}
public function signUp(User $user) {
$accountId = $this->accountController->add($user->name, $user->password);
$this->emailController->add($user->email, $accountId);
$this->accountCompanyController->add($accountId, $user->companyId, $user->access);
$this->toolMailer->adminWelcome($user->name, $user->email, $user->password);
}
}
让我们重写您的抽象 StaffRecord.php:(我认为没有变化)
<?php
namespace main;
use main\UserFactory;
abstract class StaffRecord extends UserFactory {
protected $staffController;
function __construct() {
parent::__construct();
$this->staffController = new \stdClass(); //staffController
}
}
用户管理器:
<?php
namespace main;
use main\AbstractUser;
class UserManager extends AbstractUser implements UserInterface {
public $shopId;
public $access;
public function __construct($email, $name, $password, $shopId) {
parent::__construct($email, $name, $password);
$this->shopId = $shopId;
$this->access = UserFactory::MANAGER;
}
}
经理记录:
<?php
namespace main;
use main\StaffRecord;
use main\UserInterface as User;
class ManagerRecord extends StaffRecord {
public function signUp(User $user) {
$accountId = $this->accountController->add($user->name, $user->password);
$this->emailController->add($user->email, $accountId);
$this->staffController->add($accountId, $user->shopId, $user->access);
$this->toolMailer->managerWelcome($user->name, $user->email, $user->password);
}
}
用户销售员:
<?php
namespace main;
use main\AbstractUser;
class UserSalesman extends AbstractUser implements UserInterface {
public $cpf;
public $access;
public $shopId;
public function __construct($email, $name, $password, $cpf, $shopId) {
parent::__construct($email, $name, $password);
$this->shopId = $shopId;
$this->cpf = $cpf;
$this->access = UserFactory::SALESMAN;
}
}
销售员记录:
<?php
namespace main;
use main\StaffRecord;
use main\UserInterface as User;
class SalesmanRecord extends StaffRecord {
public function signUp(User $user) {
$accountId = $this->accountController->addSeller($user->name, $user->password, $user->cpf);
$this->emailController->add($user->email, $accountId);
$this->staffController->add($accountId, $user->shopId, $user->access);
$this->toolMailer->salesmanWelcome($user->name, $user->email, $user->password);
}
}
用户客户:
<?php
namespace main;
use main\AbstractUser;
class UserCustomer extends AbstractUser implements UserInterface {
public $cpf;
public $phone;
public $birthday;
public $gender;
public function __construct($email, $name, $password, $phone, $birthday, $gender) {
parent::__construct($email, $name, $password);
$this->phone = $phone;
$this->birthday = $birthday;
$this->gender = $gender;
$this->access = UserFactory::CUSTOMER;
}
}
客户记录:
<?php
namespace main;
use main\UserInterface;
use main\UserInterface as User;
class CustomerRecord extends UserFactory {
protected $customerController;
function __construct() {
parent::__construct();
$this->customerController = new \stdClass(); //customerController
}
public function signUp(User $user) {
$accountId = $this->accountController->addCustomer($user->name, $user->password, $user->cpf, $user->phone, $user->birthday, $user->gender);
$this->emailController->add($user->email, $accountId);
$this->toolMailer->customerWelcome($user->name, $user->email, $user->password);
}
}
我是这样用的;
使用 loader.php:
<?php
function __autoload($class)
{
$parts = explode('\\', $class);
require end($parts) . '.php';
}
php main.php
<?php
namespace main;
include_once "loader.php";
use main\AdminRecord;
use main\UserAdmin;
use main\UserFactory;
use main\ManagerRecord;
use main\UserSalesman;
use main\CustomerRecord;
$userAdmin = new UserAdmin('francis@email.com', 'francis', 'test', 1);
$adminRecord = new AdminRecord($userAdmin);
$userManager = new UserManager('francis@email.com', 'francis', 'test', 1);
$managerRecord = new ManagerRecord($userManager);
$salesMan = new UserSalesman('francis@email.com', 'francis', 'test', 2, 1);
$salesmanRecord = new SalesmanRecord($salesMan);
//$email, $name, $password, $phone, $birthday, $gender
$customer = new UserCustomer('francis@email.com', 'francis', 'test', '0988-2293', '01-01-1984', 'Male');
$customerRecord = new CustomerRecord($customer);
print_r($adminRecord);
print_r($userManager);
print_r($salesMan);
print_r($salesmanRecord);
print_r($customer);
print_r($customerRecord);
下载文件:https://www.dropbox.com/sh/ggnplthw9tk1ms6/AACXa6-HyNXfJ_fw2vsLKhkIa?dl=0
我创建的解决方案并不完美,仍然需要重构和改进。
希望这能解决您的问题。
谢谢。
关于php - 没有方法重载的 PHP 中的抽象工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28117856/
假设我有一个类,我在其中重载了运算符 == : Class A { ... public: bool operator== (const A &rhs) const; ... };
我知道你不应该使用 std::find(some_map.begin(), some_map.end()) 或 std::lower_bound,因为它会采用线性时间而不是 some_map.lowe
我正在尝试在 Haskell 中定义 Vector3 数据类型,并允许在其上使用 (+) 运算符。我尝试了以下方法: data Vector3 = Vector3 Double Double Doub
我已经为我的类图将运算符重载为“-”。它的用途并不完全直观(糟糕的编码 - 我知道)但是如果我做 graph3 = graph2-graph1 那么图 3 是应该只接收图 2 和图 1 中的那些顶点。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Operator overloading 我想重载 以按字母顺序排列字符串,但我不确定该怎么做。 如何再次
下面的代码给我一个编译错误。谁能告诉我为什么? class mytype { public: int value; mytype(int a) { value = a;
这有什么问题吗? class Vec2 attr_accessor :x, :y # ... def += (v) @x += v.x @y += v.y retu
是否可以重载 [] 运算符两次?允许这样的事情:function[3][3](就像在二维数组中一样)。 如果可能的话,我想看看一些示例代码。 最佳答案 您可以重载 operator[] 以返回一个对象
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
我有一个网页,在某个时候显示一个导航栏,它只不过是一个 a 元素的列表 (ul)。所述 a 元素的大多数样式规则都是通用的。唯一应该改变的部分是要显示的图像,可以从列表中每个 li 元素的 id 标签
我对使用/重载“范围步长”运算符(.. ..)很感兴趣,但我终其一生都无法了解如何使用它。 在文档中它说 // Usage: start .. step .. finish 但是在 F# shell
Java 11(可能无关紧要): public static String toString(Object obj) { return ReflectionToStringBuilder.to
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我无法理解以下代码(针对行号进行注释) class Base { void m1(Object o) { } void m2(String o) { } } publi
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
class myclass{ //definitions here }; myclass e; int myarray[10]; /* Do something... */ e = myarray;
为什么不能将下标运算符(operator [])作为 friend 函数重载? 最佳答案 正如Bjarne Stroustrup在D&E book中所说: However, even in the o
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
因此,我有一个问题是我最近尝试重载 namespace Eng { /** * A structure to represent pixels */ typedef
如何重载onResume()以正确的方式工作?我想从 activity 返回到 MainActivity ,我希望在其中具有与应用程序启动后相同的状态。我想使用 recreate() 但它循环了或者类
我是一名优秀的程序员,十分优秀!