이 모델은 이해하기 다소 모호할 수 있으며, 특히 일부 책에서는 설명이 어렵습니다. 먼저 조합 모델의 몇 가지 특징에 대해 이야기해 보겠습니다.
1. 분할할 수 없는 기본 요소가 있어야 합니다.
2. 결합된 개체는 결합될 수 있습니다.
일반적인 예를 들자면 원자는 화학 반응의 기본 입자이며 화학 반응에서 나눌 수 없습니다. 이제 C(탄소), H(수소), O(산소), N(질소)의 네 가지 유형의 원자가 무작위로 결합되어 단백질이든 지방이든 무수한 분자가 될 수 있습니다. 단백질과 지방은 고기, 콩 등에 결합될 수 있습니다.
본론으로 돌아가서, 고객이 나뭇잎의 크기와 색상을 설정하고 이름을 지정할 수 있어야 한다는 요구 사항이 있습니다.
abstract class tree{ abstract function create(); } class createLeaf extends tree{ private $name; private $size; private $color; private $leaf=array(); public function __construct($name,$size,$color){ $this->name=$name; $this->size=$size; $this->color=$color; } public function create(){ $this->leaf[$this->name]=array( 'size'=>$this->size, 'color'=>$this->color ); return $this->leaf; } } $leaf=new createLeaf('大红树叶','大','红'); print_r($leaf->create()); 运行以上代码将得到: Array ( [大红树叶] => Array ( [size] => 大 [color] => 红 ) )
저희 디자인은 고객의 요구를 완벽하게 충족시켰지만 이제 고객의 새로운 요구 사항이 다가오고 있습니다. 나뭇잎을 만들 수 있을 뿐만 아니라 가지를 만들 수 있고 배치할 수도 있습니다. 나뭇가지에 나뭇잎 설치된 나뭇잎을 나뭇가지에서 제거할 수도 있습니다. 그들이 궁극적으로 원하는 것은 가지 위에 다른 가지를 배치하여 잎이 많은 나무를 만들 수 있다는 것입니다.
분석: 나뭇잎을 만드는 것과 가지를 만드는 것은 둘 다 생성 연산을 가지므로 둘 다 가능합니다. 추상 트리 클래스가 구현되어 있지만 가지를 생성하는 클래스에도 삽입 및 제거 작업이 필요하므로 임시로 두 가지 추상 메서드인 Combination() 및 Separation()을 트리 클래스에 추가합니다.
abstract class tree{ abstract function create();//创建 abstract function combination(tree $item);//组合 abstract function separation(tree $item);//分离 } class createLeaf extends tree{ private $name; private $size; private $color; private $leaf=array(); public function __construct($name,$size,$color){ $this->name=$name; $this->size=$size; $this->color=$color; } public function create(){ $this->leaf[$this->name]=array( 'size'=>$this->size, 'color'=>$this->color ); return $this->leaf; } //由于创建叶子类不需要组合和分离的操作,我们将这两个方法投掷出错误警告。 public function combination(tree $item){ throw new Exception("本类不支持组合操作"); } public function separation(tree $item){ throw new Exception("本类不支持分离操作"); } } class createBranch extends tree{ private $name; private $branch=array(); private $items=array();//树枝可能被安插叶子,该变量用于存放叶子对象 public function __construct($name){ $this->name=$name; } //我们已经知道$items内的对象都包含创建操作,所以只要依次执行各对象的创建操作,收集结果便可 public function create(){ foreach($this->items as $item){ $arr=$item->create(); $this->branch[$this->name][]=$arr; } if(empty($this->branch)){ $this->branch[$this->name]=array(); } return $this->branch; } public function combination(tree $item){ $this->items[]=$item; } public function separation(tree $item){ $key=array_search($item,$this->items); if($key!==false){ unset($this->items[$key]); } } } $leaf_1=new createLeaf('大红树叶','大','红'); $leaf_2=new createLeaf('大绿树叶','大','绿'); $leaf_3=new createLeaf('大黄树叶','大','黄'); $leaf_4=new createLeaf('小红树叶','小','红'); $leaf_5=new createLeaf('小绿树叶','小','绿'); $leaf_6=new createLeaf('小黄树叶','小','黄'); $branch_1=new createBranch('树枝1号'); $branch_1->combination($leaf_1); $branch_1->combination($leaf_2); $branch_1->combination($leaf_3); $branch_2=new createBranch('树枝2号'); $branch_2->combination($leaf_4); $branch_2->combination($leaf_5); $branch_2->combination($leaf_6); $branch=new createBranch('树干'); $branch->combination($branch_1); $branch->combination($branch_2); print_r($branch->create()); 运行以上代码将得到: Array ( [树干] => Array ( [0] => Array ( [树枝1号] => Array ( [0] => Array ( [大红树叶] => Array ( [size] => 大 [color] => 红 ) ) [1] => Array ( [大绿树叶] => Array ( [size] => 大 [color] => 绿 ) ) [2] => Array ( [大黄树叶] => Array ( [size] => 大 [color] => 黄 ) ) ) ) [1] => Array ( [树枝2号] => Array ( [0] => Array ( [小红树叶] => Array ( [size] => 小 [color] => 红 ) ) [1] => Array ( [小绿树叶] => Array ( [size] => 小 [color] => 绿 ) ) [2] => Array ( [小黄树叶] => Array ( [size] => 小 [color] => 黄 ) ) ) ) ) )
이 요구 사항을 훌륭하게 완료하여 큰 나무가 생성되었습니다
. 그러나 여기에 문제가 있습니다. 나뭇잎을 만드는 데에는 Combination() 및 분리()가 필요합니다. 추상 클래스 트리를 두 클래스로 분할하면 어떨까요?
abstract class tree{ abstract function create(); } //拆分出的树干抽象类,由于继承自tree,必须将create()实现,但实现create()又会造成代码重复,所以将此类也申明为抽象类 abstract class branch extends tree{ abstract function combination(tree $item); abstract function separation(tree $item); } class createLeaf extends tree{ private $name; private $size; private $color; private $leaf=array(); public function __construct($name,$size,$color){ $this->name=$name; $this->size=$size; $this->color=$color; } public function create(){ $this->leaf[$this->name]=array( 'size'=>$this->size, 'color'=>$this->color ); return $this->leaf; } public function combination(tree $item){ throw new Exception("本类不支持组合操作"); } public function separation(tree $item){ throw new Exception("本类不支持分离操作"); } } class createBranch extends branch{ private $name; private $branch=array(); private $items=array(); public function __construct($name){ $this->name=$name; } public function create(){ foreach($this->items as $item){ $arr=$item->create(); $this->branch[$this->name][]=$arr; } if(empty($this->branch)){ $this->branch[$this->name]=array(); } return $this->branch; } public function combination(tree $item){ $this->items[]=$item; } public function separation(tree $item){ $key=array_search($item,$this->items); if($key!==false){ unset($this->items[$key]); } } } $leaf_1=new createLeaf('大红树叶','大','红'); $leaf_2=new createLeaf('大绿树叶','大','绿'); $leaf_3=new createLeaf('大黄树叶','大','黄'); $leaf_4=new createLeaf('小红树叶','小','红'); $leaf_5=new createLeaf('小绿树叶','小','绿'); $leaf_6=new createLeaf('小黄树叶','小','黄'); $branch_1=new createBranch('树枝1号'); $branch_1->combination($leaf_1); $branch_1->combination($leaf_2); $branch_1->combination($leaf_3); $branch_2=new createBranch('树枝2号'); $branch_2->combination($leaf_4); $branch_2->combination($leaf_5); $branch_2->combination($leaf_6); $branch=new createBranch('树干'); $branch->combination($branch_1); $branch->combination($branch_2); print_r($branch->create());
이렇게 해서 우리는 마침내 이 요구 사항을 아름답게 충족시켰습니다. 하지만 구성 패턴의 유연성으로 인해 많은 사람들이 생각 없이 구성 클래스를 사용하는 것을 좋아한다는 점에 유의해야 합니다. 실제로 조합 클래스에는 "너무 유연하다"는 단점과 "오버헤드가 높다"는 단점이 있습니다. 시스템 전체에서 요소나 조합이 여러 번 호출될 수 있지만 시스템의 한 노드에서 특정 요소나 조합에 문제가 발생하면 해당 노드의 문제를 해결하기가 어려울 것이라고 가정해 보겠습니다.
다시 한번 상상해 보십시오. 시스템의 특정 요소가 데이터베이스를 쿼리하는 SQL 문이고, 이 SQL 문의 오버헤드가 다소 높다면, 일단 전체 시스템의 구석구석에 결합되면 실행되는 시스템은 결과를 비참하게 만들 것입니다.
위 내용은 PHP 객체지향 개발 - 조합모드 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(m.sbmmt.com)를 참고해주세요!