This model can be somewhat ambiguous to understand, especially the difficult explanations in some books. Let’s first talk about several characteristics of the combination model:
1. There must be indivisible basic elements.
2. The combined objects can be combined.
To give a popular example, atoms are the basic particles of chemical reactions, and they are indivisible in chemical reactions. There are now four types of atoms, C (carbon), H (hydrogen), O (oxygen), and N (nitrogen), which can be randomly combined into countless molecules, either protein or fat. Protein and fat are combinations. Protein and fat can be combined into meat, soybeans, etc.
Back to the topic, there is now a requirement. The customer needs to create a leaf, set the leaf size and color, and name the leaf.
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] => 红 ) )
Our design perfectly fulfilled the customer's needs, but now the customer's new requirements are coming, not only to be able to create leaves, but also to be able to create branches, and to be able to place leaves on the branches, You can also remove the installed leaves from the branches. What they ultimately want is that other branches can be placed on the branches to build a leafy tree
Analysis: Creating leaves and creating branches both have creation operations, so they can both The abstract tree class is implemented, but the class that creates the branches also requires insertion and removal operations, so for the time being, we add two abstract methods combination() and separation() to the tree class.
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] => 黄 ) ) ) ) ) )
We completed this requirement beautifully, and a big tree was created by us
, but there is a problem. Creating leaves only requires the create() operation, and does not require combination. () and separation(), why don't we split the abstract class tree into two classes?
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());
In this way, we finally fulfilled this requirement beautifully. But it must be noted that due to the flexibility of the composition pattern, many people like to use composition classes without thinking. In fact, the combination class has the defects of "too flexible" and "high overhead". Let's imagine that an element or combination may be called many times throughout the system, but once there is a problem with a certain element or combination at a node in the system, it will be difficult for us to troubleshoot that node.
Imagine again, if a certain element in the system is a SQL statement that queries the database, and the overhead of this SQL statement is somewhat high, once it is combined into every corner of the entire system, the running system will cause The results will be catastrophic.
The above is the content of the combination mode of PHP object-oriented development. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!