多态金额基类的使用确实是OOP的核心。但是,在一些阶段,我必须创建积累的子类的一个具体事例。这个通常是用工厂模式实现的。一个工厂类拥有一个静态的方法,用来接收一些输入,并根据输入决定应该创建那个类的实例(通常是一个子类)。
假定在你的Web站点上,有着不同类型的用户登录。其中一些人是游客,一些是正常的会员,还有其他一些人是管理员。一个普通的思路是,你会需要一个基类User和三个字类:GustUser、CustomerUser和AdminUser。与User一样的是,他的子类包含用户的获取信息的方法(例如,他们访问Web站点的权限和个人的首选项)。
对你来说,编写你的Web应用最好的方法就是尽可能多的使用基类User,这样代码将会比较规范而且很容易在需求增加时加上附加的用户类型。
下面的例子先是一种关于四个User类的实现方式,而且使用UserFactory类来根据用户名创建合适的用户对象:
name=$name;
}
function getName(){
return $this->name;
}
function hasReadPermission(){
return true;
}
function hasModifyPermission(){
return false;
}
function hasDeletePermission(){
return false;
}
function wantsFlashInterface(){
return true;
}
}
/**
* 游客
* Class GuestUser
*/
class GuestUser extends User{
}
/**
* 会员
* Class CustomerUser
*/
class CustomerUser extends User{
function hasModifyPermission()
{
return true;
}
}
/**
* 管理员
* Class AdminUser
*/
class AdminUser extends User{
function hasModifyPermission()
{
return true;
}
function hasDeletePermission()
{
return true;
}
function wantsFlashInterface()
{
return false;
}
}
/**
* 工厂类
* Class UserFactory
*/
class UserFactory{
private static $users = [
'Andi'=>"admin",
'Stig'=>"guest",
'Derick'=>"customer"
];
static function Create($name)
{
if (!isset(self::$users[$name])){
//报错,因为用户不存在
}
switch (self::$users[$name])
{
case "guest":
return new GuestUser($name);
case "customer":
return new CustomerUser($name);
case "admin":
return new AdminUser($name);
default:
//报错
}
}
}
function boolToStr($b)
{
if ($b == true)
{
return "Yes \n";
}else{
return "No \n";
}
}
function displayPermissions(User $obj)
{
print $obj->getName() . "'s permissions:\n";
print "Read:".boolToStr($obj->hasReadPermission());
print "Modify:".boolToStr($obj->hasModifyPermission());
print "Delete:".boolToStr($obj->hasDeletePermission());
}
function displayRequirements(User $obj)
{
if ($obj->wantsFlashInterface())
{
print $obj->getName() . " requires Flash\n";
}
}
$logins = ['Andi',"Stig","Derick"];
foreach ($logins as $login)
{
displayPermissions(UserFactory::Create($login));
displayRequirements(UserFactory::Create($login));
}
运行这个代码输出
这个代码片段是一个经典的工厂模式的例子。你拥有一个类分层(在这里,user分级),但是你的代码如下displayPermissions()采用同样的方法处理。唯一一个用不同的方法处理类的就是工厂本身,它负责构造这些实例。在这个例子中,工厂检查用户名属于哪一种类型的用户并创建与它对应的实例。在实际开发中,与把用户存在用户名映射的一个静态数组中不同的是,你可能会把用户信息存储在数据库或者配置文件中。
提示:除了create(),你讲经常能发现其他用于工厂方法的名字,例如factory(),factoryMethod(),或者createInstance()。