开发者

Design Question: Which is Better practice?

开发者 https://www.devze.com 2022-12-16 02:19 出处:网络
I have 3 different web servers which handle user data (username/passwd/email/etc.). I have 3 different web service calls respectively, so I\'ve created 3 different classes which calls for the same inf

I have 3 different web servers which handle user data (username/passwd/email/etc.). I have 3 different web service calls respectively, so I've created 3 different classes which calls for the same information (getUsername, setUsername, getEmail, setEmail, etc.). From the main class I instantiate each webservice-call objects and when I have a request for 开发者_开发百科a new username, password I call the createUsername() method of each class (provisioning the data).

Do you have any suggestions on how to apply a design pattern for this problem? I thought of making a class which will have a method createUsername() {} and in this I would call each of the webservice-classes and store each result in a predefined array. Does anyone have any suggestion or a better practice?

currently i have:


class webservice1calls {
function createUser($username, $password) {}
function deleteUser($username, $password) {}
function createGroup($groupname) {}
function deleteGroup($groupname) {}
}

class webService2calls { function createUser($username, $password) {} //different implementation function deleteUser($username, $password) {} //different implementation function createGroup($groupname) {} //different implementation function deleteGroup($groupname) {} //different implementation }

class webService3calls { function createUser($username, $password) {} //different implementation function deleteUser($username, $password) {} //different implementation function createGroup($groupname) {} //different implementation function deleteGroup($groupname) {} //different implementation }

//My "like a proxy" class:

class webServiceCalls { function createUser($username, $password) { $ws1 = new webService1calls(); $ws2 = new webService2calls(); $ws3 = new webService3calls();

$res1 = $ws1->createUser($username, $password);
$res2 = $ws2->createUser($username, $password);
$res3 = $ws3->createUser($username, $password);

// return result depending $res1,$res2 and $res3 values

}

//and the call is done from another class somewhat like this:

class doThings { function run() { $ws = new webServiceCalls(); $ws_res = $ws->createUser(); } }

I thought that the above representation would help you understand the current design (and maybe a better understanding of the problem. thanks!


Eep! Firstly, since these are so similar, they should share a common base class or use an interface:

interface WebService {
    function createUser($username, $password);
    function deleteUser($username, $password);
    function createGroup($groupname);
    function deleteGroup($groupname);
}

class MyService implements WebService {
    function createUser($username, $password) {}
    function deleteUser($username, $password) {}
    function createGroup($groupname) {}
    function deleteGroup($groupname) {}
}

Secondly, I hope your services aren't actually called 1,2,3. If they are, that suggests to me that maybe you should be using some form of an array.

I don't like your idea of a "proxy" class. Are you always using all 3 services, or is this some sort of library where you just include the service you need? You haven't provided enough info about what you're actually trying to accomplish.


I like the idea of keeping each server's implementation in a separate class, and I also like Mark's idea of utilizing an interface. I'm also fond of your idea of a proxy class, but not in the form that you presented. I would create a class that acts as a pool of sorts. Something like this:

class WebServicePool implements WebService {

    private $webServices = array();

    public function registerWebService($service) {
        if($service instanceof WebService)
            $this->webServices[] = $service;
    }

    function createUser($username, $password) {
        foreach($this->webServices as $service)
            $service->createUser($username, $password);
    }
    // ...
}

You could also use magic methods to proxy this functionality:

class WebServicePool {

    private $webServices = array();

    public function registerWebService($service) {
        if($service instanceof WebService)
            $this->webServices[] = $service;
    }

    function __call($name, $arguments) {
        foreach($this->webServices as $service)
            call_user_func_array(array($service, $name), $arguments);
    }
}

That way, if you add more functions to your interface, you won't need to update your pool class. Hope this helps!


What do you think about a Model - ModelMapper arch? Zend Framework uses this approach. You could have possibily the following classes: (silly naming convention for better understanding)

  • Model_User
  • Mapper_User_Email
  • Mapper_User_Name
  • Mapper_User_Password

And the individual mappers read the needed data, the 3rd party class only calls Model_User->getName()

Edit: Example usage:

//simple code:
$user = new Model_User();
echo "Your name is: " . $user->getName();

//Model_User:
public function getName() {
    if($this->_name = null) {
        $this->getNameMapper()->getName($this);
        //getNameMapper() returns a Mapper_User_Name object
    }
    return $this->getName();
}   

//Mapper_User_Name:
public function getName($user) {
    $name = "john"; /*magic here, the class communicate with the service that holds names*/
    $user->setName($name);
}

Example only, the getters and setters could be more defensive.


I would take a completely different approach. A REST interface would be perfect for what you're trying to do, which are the standard CRUD commands.

0

精彩评论

暂无评论...
验证码 换一张
取 消