Design pattern for users
I'm starting to code my project and I have used, in some past unfinished project, two different patterns to manage the design of a user class that will need to manage the following things:
- The creation of a user
- The edits to a user
- The deletion of a user
- The reading of user data
Despite this, we have also to consider that this user class will be extended by the session class which will just set the focused user id as the id provided by the user who is viewing the pages.
We will also have this class users
that will manage instead groups of users.
The 2 options I used are the following (simplified):
Different class for different purpose
- class UserMaker($username, $pass开发者_Python百科word, $email);
function giveBirth(); // create the user
- class UserManager($id);
function edit($field, $value); // edit a specific user field
function save(); // save all the edits with a single query
function setTrusted(); // set that user as trusted
function setAdmin(); // set that user as admin
function setBanned(); // ban the specific user
- class UserReader($id);
function get($field); // Get the value of a single field
function getAll(); // Get all fields from that user as associative array
function isAdmin(); // self explanation
function isRegistered(); // self explanation
function isBanned(); // self explanation
Single class
- class User($id);
function static giveBirth($username, $password, $email); // create the user, notice this is static
function edit($field, $value); // edit a specific user field
function save(); // save all the edits with a single query
function setTrusted(); // set that user as trusted
function setAdmin(); // set that user as admin
function setBanned(); // ban the specific user
function get($field); // Get the value of a single field
function getAll(); // Get all fields from that user as associative array
function isAdmin(); // self explanation
function isRegistered(); // self explanation
function isBanned(); // self explanation
Basically, since the only class that does not accept $id as argument for the __construct()
is UserMaker we just set the function giveBirth()
as static so we can create the user.
What is the best way to design this pattern? Have you got a third-option which you feel better than these?
Well, the answer to this question relates specifically with The Single Responsibility Principle. Basically, each and every class in your application should have exactly one responsibility. That doesn't mean that it can't be used in more than one situation, but it shouldn't be responsible for more than one abstract concept.
So, from your examples, I would build a class structure similar to this:
class UserFactory()
getModel();
getUser($id, $model = null);
getACL($user);
class UserModel ()
edit($id = 0);
load($id = 0);
reload($id = 0);
save($id = 0);
class User ($data)
getAll();
getField($field);
class UserACL (User $user)
isTrustedUser();
isAdminUser();
isBannedUser();
That way, everything is organized by responsibility and role, rather than by relation. The benefit to this, is that if you want to swap out an individual component later (for example, the ACL system, or the Model storage layer), you don't need to worry about testing a huge class. Just test that particular API and you're done.
I do not know how exactly have you organized/conceived stuff in your system although from the approaches that I have used, I've found out that the most efficient way of handling stuff is by conceiving objects as services for example: How many times in your software will the giveBirth method be called? once, twice more ? why more?
Although let's say that your user object must expose methods which can not be called in an exact place every time or you want it to have a more general effect.
- Create an interface(or interfaces) with the methods headers.
- Create a SINGLETON that implements the interface (all the interfaces). That is because I assume you will never have more then an instance of an user during one request.(fact that is also available for the session).
in the singleton you will have an init static method which can receive an id in order to create the user instance. You will have something like this in the index as I do assume there is a single entry to your application
UserSingleton::init($_SESSION["id"]);
after the request process initializes the user object you can use this :
$user = UserSingleton::getInstance(); // will return the instance of singleton
$user->setBanned();// or whatever you need to call;
Obs: you can avoid the init method by creating the getInstanceMethod like this:
public function getInstance(){
if(!isset(self::$instance) {
self::$instance = new UserSingleton($_SESSION["user_id"]) ;
}
return self::$instance;
}
Take note that this must not handle stuff like interaction with the database, this should receive/send data to/from the database through external stuff. It is a helper not a business model/object. That is another concern.
精彩评论