六. PHP模式设计----让面向对象编程更加灵活的模式
来源:互联网 发布:国考如何备考 知乎 编辑:程序博客网 时间:2024/05/17 02:53
*问题来源
下面代码中,当军队功能变得越来越复杂时(比如支持合并,拆分),需要修改的地方就越来越多,类似军队的其他类也一样道理,维护起来很麻烦
//以"文明"游戏为背景...
//*战斗单元类
abstract class Unit{
//攻击强度
abstract function bombardStrength();
}
//射手
class Archer extends Unit{
function bombardStrength(){
return 4;
}
}
//激光塔
class LaserCannonUnit extends Unit{
function bombardStrength(){
return 44;
}
}
//军队:由战斗单元组成
class Army{
private $units=array();
//当军队支持合并时,则再需要一个属性
private $armys=array();
//添加单元
function addUnit(Unit $unit){
if(!empty($unit)){
array_push($this->units, $unit);
}
}
//添加军队
function addArmy(Army $army){
if(!empty($army)){
array_push($this->armys, $army);
}
}
//计算总强度
function bombardStrength(){
$ret=0;
foreach ($this->units as $unit){
$ret+=$unit->bombardStrength();
}
//当支持军队合并时,则计算总强度需要增加下面代码
foreach ($this->armys as $army){
$ret+=$army->bombardStrength();
}
return $ret;
}
//移动能力,防御能力...省略
}
//运兵船:一个类似军队的单元,它具备10个战斗单元,有攻击力
class TroopCarrier{
//具备和军队差不多的方法和属性
}
$armyA=new Army();
$armyA->addUnit(new Archer());
$armyA->addUnit(new LaserCannonUnit());
$armyB=new Army();
$armyB->addUnit(new Archer());
$armyB->addUnit(new Archer());
$armyA->addArmy($armyB);
print $armyA->bombardStrength();//==>56
1 组合模式
组合模式用于解决上面例子出现的那类问题....(接下去有几个修正的例子)
//以"文明"游戏为背景...
//运用组合模式,把军队和运兵车也当作Unit的组合对象
//*战斗单元类
abstract class Unit{
abstract function addUnit(Unit $unit);
abstract function removeUnit(Unit $unit);
//攻击强度
abstract function bombardStrength();
}
//射手
class Archer extends Unit{
function bombardStrength(){
return 4;
}
function addUnit(Unit $unit){
}
function removeUnit(Unit $unit){
}
}
//激光塔
class LaserCannonUnit extends Unit{
function bombardStrength(){
return 44;
}
function addUnit(Unit $unit){
}
function removeUnit(Unit $unit){
}
}
//军队:由战斗单元组成
class Army extends Unit{
private $units=array();
//添加单元
function addUnit(Unit $unit){
if(!empty($unit)){
if(in_array($unit, $this->units,true)){
return;
}
array_push($this->units, $unit);
}
}
function removeUnit(Unit $unit){
$this->units=array_udiff($this->units, array($unit), function ($a,$b){return ($a===$b?0:1);});
}
//计算总强度
function bombardStrength(){
$ret=0;
foreach ($this->units as $unit){
$ret+=$unit->bombardStrength();
}
return $ret;
}
//移动能力,防御能力...省略
}
//运兵船:一个类似军队的单元,它具备10个战斗单元,有攻击力
class TroopCarrier extends Unit{
//具备和军队差不多的方法和属性
function bombardStrength(){
}
function addUnit(Unit $unit){
}
function removeUnit(Unit $unit){
}
}
$main_army=new Army();
//添加一些Unit对象
$main_army->addUnit(new Archer());
$main_army->addUnit(new LaserCannonUnit());
$sub_army=new Army();
$sub_army->addUnit(new Archer());
$sub_army->addUnit(new Archer());
$main_army->addUnit($sub_army);
print $main_army->bombardStrength();
*1.修正上一个例子中抽象类强制性的不必要的方法(缺点:子类未被强制要求实现addUnit()等,这是一个大问题)
//以"文明"游戏为背景...
//运用组合模式,把军队和运兵车也当作Unit的组合对象
//*战斗单元类
abstract class Unit{
function addUnit(Unit $unit){
return new Exception(get_class($this)." is a leaf");
}
function removeUnit(Unit $unit){
return new Exception(get_class($this)." is a leaf");
}
//攻击强度
abstract function bombardStrength();
}
//射手
class Archer extends Unit{
function bombardStrength(){
return 4;
}
}
//激光塔
class LaserCannonUnit extends Unit{
function bombardStrength(){
return 44;
}
}
//军队:由战斗单元组成
class Army extends Unit{
private $units=array();
//添加单元
function addUnit(Unit $unit){
if(!empty($unit)){
if(in_array($unit, $this->units,true)){
return;
}
array_push($this->units, $unit);
}
}
function removeUnit(Unit $unit){
$this->units=array_udiff($this->units, array($unit), function ($a,$b){return ($a===$b?0:1);});
}
//计算总强度
function bombardStrength(){
$ret=0;
foreach ($this->units as $unit){
$ret+=$unit->bombardStrength();
}
return $ret;
}
//移动能力,防御能力...省略
}
//运兵船:一个类似军队的单元,它具备10个战斗单元,有攻击力
class TroopCarrier extends Unit{
//具备和军队差不多的方法和属性
function bombardStrength(){
}
function addUnit(Unit $unit){
}
function removeUnit(Unit $unit){
}
}
$main_army=new Army();
//添加一些Unit对象
$main_army->addUnit(new Archer());
$main_army->addUnit(new LaserCannonUnit());
$sub_army=new Army();
$sub_army->addUnit(new Archer());
$sub_army->addUnit(new Archer());
$main_army->addUnit($sub_army);
print $main_army->bombardStrength();
print "\n";
print (new Archer())->addUnit(new Archer());
*2. 增加一个继承自Unit的抽象类CompositeUnit,让复杂的类直接继承CompositeUnit,简单类继承Unit,再把复杂类必备的特殊接口放在CompositeUnit类里
//以"文明"游戏为背景...
//运用组合模式,把军队和运兵车也当作Unit的组合对象
//本例子需要解决一个问题,就是如何区分Unit的实例是否支持addUnit等方法?
//解决方案就是在Unit中增加一个方法getComposite(),默认返回null,只有CompositeUnit类的实例才会返回非null
//*战斗单元类
abstract class Unit{
//攻击强度
abstract function bombardStrength();
function getComposite(){
return null;
}
}
//复合抽象类
abstract class CompositeUnit extends Unit{
protected $units=array();
//可以不用写bombardStrength()
function getComposite(){
return $this;
}
//添加单元
function addUnit(Unit $unit){
if(!empty($unit)){
if(in_array($unit, $this->units,true)){
return;
}
array_push($this->units, $unit);
}
}
function removeUnit(Unit $unit){
$this->units=array_udiff($this->units, array($unit), function ($a,$b){return ($a===$b?0:1);});
}
}
//射手
class Archer extends Unit{
function bombardStrength(){
return 4;
}
}
//激光塔
class LaserCannonUnit extends Unit{
function bombardStrength(){
return 44;
}
}
//军队:由战斗单元组成
class Army extends CompositeUnit{
//计算总强度
function bombardStrength(){
$ret=0;
foreach ($this->units as $unit){
$ret+=$unit->bombardStrength();
}
return $ret;
}
//移动能力,防御能力...省略
}
//运兵船:一个类似军队的单元,它具备10个战斗单元,有攻击力
class TroopCarrier extends CompositeUnit{
//具备和军队差不多的方法和属性
function bombardStrength(){
//Do something...
}
}
//UnitScript类:用于合并等操作
class UnitScript{
/**
* 返回合并后的对象
* @param Unit $newUnit 新来者
* @param Unit $occupyingUnit 占据着
*/
static function joinExisting(Unit $newUnit,Unit $occupyingUnit){
$comp=$occupyingUnit;
if(!is_null($comp->getComposite())){
//该方法不会自动识别到...
$comp->addUnit($newUnit);
return $comp;
}
$comp=new Army();
$comp->addUnit($newUnit);
$comp->addUnit($occupyingUnit);
return $comp;
}
}
$unitScript=new UnitScript();
$army=$unitScript->joinExisting(new Archer(), new LaserCannonUnit());
$army=$unitScript->joinExisting($army, new Archer());
print $army->bombardStrength();
2. 装饰模式
问题背景:如果每一个功能都建立在继承上,比如Tile(区域)为父类,钻石区域和污染区域为子类,这时候若需要一个被污染的钻石区域,那么就需要再定义一个新类出来,问题一旦更复杂,类就会爆炸式增长...
//装饰模式就是使用组合和委托,Decorator类会保存另一个类的实例,这样就可以像套管道一样,一个套
//一个来实现不同的组合功能
abstract class Tile{
//获取区域收益
abstract function getWealthFactor();
}
class Plains extends Tile{
private $wealthFactor=2;
function getWealthFactor(){
print "Call ".__CLASS__."\n";
return $this->wealthFactor;
}
}
//抽象装饰类
abstract class TileDecorator extends Tile{
//一个用于保存Tile实例的可继承属性
protected $tile;
function __construct(Tile $tile){
$this->tile=$tile;
}
}
//钻石装饰类
class DiamondDecorator extends TileDecorator{
function getWealthFactor(){
print "Call ".__CLASS__."\n";
return $this->tile->getWealthFactor()+2;
}
}
//污染装饰类
class PollutionDecorator extends TileDecorator{
function getWealthFactor(){
print "Call ".__CLASS__."\n";
return $this->tile->getWealthFactor()-4;
}
}
$tile=new Plains();
print "平原收益为:".$tile->getWealthFactor();//==>2
print "\n";
//用管道方式定义一个被污染的钻石区域
$pollutionDiamon=new PollutionDecorator(new DiamondDecorator(new Plains()));
print "被污染的钻石平原收益为:".$pollutionDiamon->getWealthFactor();//(2+2-4)==>0
3.外观模式
系统部分功能的实现是利用子系统,所以把这部分系统功能封装成一个单一接口,供外界调用几段过程是代码实现一个几个功能,再建立一个类把这些功能封装在一起,利用过程式代码再实现一个全新的功能.
function getProductFileLines($file){
return file($file);
}
function getProductObjectFromId($id,$productName){
return new Product($id,$productName);
}
function getNameFromLine($line){
if(preg_match("/.*-(.*)\s\d+/", $line,$array)){
return str_replace('_', ' ', $array[1]);
}
return '';
}
function getIDFromLine($line){
//$array第一个为完全匹配项(234-),第二个开始为子匹配项(234)
if(preg_match("/^(\d{1,3})-/", $line,$array)){
return $array[1];
}
return -1;
}
class Product{
public $id;
public $name;
function __construct($id,$name){
$this->id=$id;
$this->name=$name;
}
}
//用来实现外观模式的类
class ProductFacade{
private $products=array();
function __construct($file){
$this->file=$file;
$this->compile();
}
function compile(){
$aryFile=getProductFileLines($this->file);
foreach ($aryFile as $line){
$id=getIDFromLine($line);
$name=getNameFromLine($line);
$this->products[$id]=getProductObjectFromId($id, $name);
}
}
function getProducts(){
return $this->products;
}
function getProduct($id){
return $this->products[$id];
}
}
$facade=new ProductFacade("src/myResource.txt");
$facade->getProduct(234);
print_r($facade);
/*=>ProductFacade Object
(
[products:ProductFacade:private] => Array
(
[234] => Product Object
(
[id] => 234
[name] => bom jumper
)
[445] => Product Object
(
[id] => 445
[name] => Cow hat
)
)
[file] => src/myResource.txt
)
*/
0 0
- 六. PHP模式设计----让面向对象编程更加灵活的模式
- 深入PHP面向对象、模式与实践——让面向对象编程更加灵活的模式(2)
- 深入PHP面向对象、模式与实践——让面向对象编程更加灵活的模式(3)
- 【读书笔记-重构与模式】 组合模式-让面向对象更加灵活
- 慕课网----大话PHP设计模式 六(面向对象编程的基本原则,自动加载config)
- PHP面向对象编程设计模式(一)策略模式
- PHP面向对象编程设计模式(三)工厂模式
- PHP面向对象编程设计模式(四)观察者模式
- 面向对象的设计模式(六),状态模式
- php面向对象设计模式
- PHP面向对象设计模式
- 面向对象设计和过程式编程(6.2)《深入PHP:面向对象、模式与实践》
- 面向对象的设计模式
- 面向对象的设计模式
- 面向对象的设计模式
- php面向对象编程 – 观察者模式
- js 设计模式 oop 面向对象编程
- js 设计模式 oop 面向对象编程
- CLR存储过程
- 面向对象--枚举
- (转)getDefinitionByName,getQualifiedClassName,getQualifiedSuperclassName用法
- Ubuntu环境下挂载新硬盘
- 做APM领域德国队,笃信技术和极简体验的听云打造历程
- 六. PHP模式设计----让面向对象编程更加灵活的模式
- [转]计算机视觉的大神
- addEventListener和attachEvent区别
- mfc扩展dll 的调用以及dll中creat出错分析
- 分布式系统中的一致性和可用性
- C++ WIN 文件夹遍历
- 1411031037-hd-Doubles
- 数据库质疑修复总结 For SQL Server 2000/2005/2008/2008R2
- 库克告别乔布斯式简单粗暴 苹果正在变得更亲民