vider implements PersonProvider
{
public function getPerson($givenName, $familyName)
{
/* pretend to go to the database, get the person... */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");
return $person;
}
}
class PersonProviderFactory
{
public static function createProvider($type)
{
if ($type == ''database'')
{
return new DBPersonProvider();
} else {
return new NullProvider();
}
}
}
$config = ''database'';
/* I need to get person data... */
$provider = PersonProviderFactory::createProvider($config);
$person = $provider->getPerson("John", "Doe");
echo($person->getPrefix());
echo($person->getGivenName());
?>
在使用接口时,尝试避免直接引用实现类。相反,使用对象外部的内容可以提供正确的实现。如果您的类将装入基于某些逻辑的实现,它仍然需要获取所有实现类的定义,并且那样做也无法取得任何效果。
您可以使用 Factory 模式来创建实现接口的实现类的实例。根据约定,factory 方法将以 create 为开头并返回接口。它可以为您的 factory 获取必要的参数以计算出应当返回哪个实现类。
在清单 7 中,createProvider() 方法只是获取 $type。如果 $type 被设为 database,工厂将返回 DBPersonProvider 的实例。从数据库中装入人员的任何新实现都不要求在使用工厂和接口的类中进行任何更改。DBPersonProvider 将实现 PersonProvider 接口并且拥有 getPerson() 方法的实际实现。
利用最弱的链接
将模块松散耦合 在一起是件好事情;它是允许您封装更改的属性之一。另外两个习惯 — “保持谨慎” 和 “避免看到美杜莎” — 可帮助您构建松散耦合的模块。要实现松散耦合的类,可通过养成降低类依赖关系的习惯实现。
坏习惯:紧密耦合
在清单 8 中,降低依赖关系并不是必须降低使用对象的客户机的依赖关系。相反,该示例将演示如何降低与正确类的依赖关系并最小化这种依赖关系。
清单 8. Address 中紧密耦合的坏习惯
复制代码 代码如下:
<?php
require_once "./AddressFormatters.php";
class Address
{
private $addressLine1;
private $addressLine2;
private $city;
private $state; // or province...
private $postalCode;
private $country;
public function setAddressLine1($line1)
{
$this->addressLine1 = $line1;
}
/* accessors, etc... */
public function getCountry()
{
return $this->country;
}
public function format($type)
{
if ($type == "inline") {
$formatter = new InlineAddressFormatter();
} else if ($type == "multiline") {
$formatter = new MultilineAddressFormatter();
} else {
$formatter = new NullAddressFormatter();
}
return $formatter->format($this->getAddressLine1(),
$this->getAddressLine2(),
$this->getCity(), $this->getState(), $this->getPostalCode(),
$this->getCountry());
}
}
$addr = new Address();
$addr->setAddressLine1("123 Any St.");
$addr->setAddressLine2("Ste 200");
$addr->setCity("Anytown");
$addr->setState("AY");
$addr->setPostalCode("55555-0000");
$addr->setCountry("US");
echo($addr->format("multiline"));
echo("\n");
echo($addr->format("inline"));
echo("\n");
?>
在 Address 对象上调用 format() 方法的代码可能看上去很棒 — 这段代码所做的是使用 Address 类,调用 format() 并完成。相反,Address 类就没那么幸运。它需要了解用于正确格式化的各种格式化方法