이번에는 PHP 프로토타입 모드의 사례분석을 가져오겠습니다. PHP 프로토타입 모드 사용 시 주의사항은 무엇인가요?
프로토타입 디자인 패턴은 복제 기술을 사용하여 인스턴스화된 객체를 복사하기 때문에 흥미롭습니다. 여기서 인스턴스는 일괄 인스턴스화된 구체적인 클래스입니다. 프로토타입 디자인 패턴의 목적은 오버헤드를 줄이는 것입니다. 클래스에서 새 객체를 인스턴스화하는 대신 기존 인스턴스의 복제를 사용할 수 있습니다.
Clone 함수
프로토타입 디자인 패턴의 핵심은 방법을 이해하는 것입니다. 내장 함수 clone()
을 사용하려면 $boy와 동일한 속성에 액세스하고 직접 인스턴스처럼 이러한 속성을 변경할 수 있는 Boy 인스턴스 $boy를 복제하여 cloneBoy 인스턴스가 생성됩니다. clone()
.
<?php abstract class CloneObject { public $name; public $picture; abstract function clone(); } class Boy extends CloneObject { public function construct() { $this->face = "handsome"; $this->name = "chenqionghe"; } public function display() { echo 'look : '.$this->face;; echo '<br />'.$this->name.'<br />'; } public function clone() {} } $boy = new Boy(); $boy->display(); $cloneBoy = clone $boy; $cloneBoy->face = "still handsome"; $cloneBoy->display();
运行结果如下
look : handsome
chenqionghe
look : still handsome
chenqionghe
$cloneBoy实例是通过克隆Boy的实例$boy, 它可以像$boy一样访问相同的属性, 而且像Boy类的直接实例一样改变这些属性.
注意: 对于所克隆的实例 , clone关键字会为该实例的类实例化另一个实例(使用克隆关键字可以创建一个类的副本, 如果可能, 会自动调用对象的clone
方法, 但不能直接调用 对象的clone
참고: 복제된 인스턴스의 경우 clone 키워드는 이 인스턴스 클래스의 다른 인스턴스를 인스턴스화합니다. clone 키워드를 사용하면 클래스의 복사본을 만들 수 있습니다. 가능하면 개체의 clone
메소드는 자동으로 호출되지만 객체의 clone 메소드는 직접 호출할 수 없습니다.
메소드), 프로세스에 대해 주의할 점은 복제가
.간단한 프로토타입 예시
초파리 연구를 예로 들어보겠습니다. 연구의 목표는 프로토타입 초파리를 만들고, 돌연변이가 발생하면 이 돌연변이 초파리를 만드는 것입니다 추상 클래스 인터페이스 및 구체적인 구현
프로토타입(IPrototype)의 두 가지 구체적인 클래스 구현은 성별 변수 및 다양한 성별의 동작을 포함하여 각각 서로 다른 성별을 나타냅니다. IPrototype의 두 구현 간의 차이는 성별에 반영됩니다. 성별은 상수로 식별됩니다. 하나는 MALE이고 다른 하나는 FEMAIL입니다. 수컷 초파리 짝짓기 뒤에는 이 부울 변수가 있습니다. 암컷 초파리에는 수컷 초파리의 번식을 나타내는 숫자 값이 포함된 $fecundity 변수가 있습니다. .php
<?php abstract class IPrototype { public $eyeColor; public $winBeat; public $unitEypes; abstract function clone(); }
Client
프로토타입 디자인 모드에서 Client 클래스는 정말 없어서는 안되는 부분입니다. 그 이유는, 서브클래스의 특정 구현이 인스턴스의 템플릿으로 사용되지만 특정 작업은 동일한 템플릿을 사용하여 인스턴스를 복제하는 작업은 Client 클래스
Client.php
<?php include_once('IPrototype.php'); class MaleProto extends IPrototype { const gender = "MALE"; public $mated; public function construct() { $this->eyeColor = "red"; $this->winBeat = "220"; $this->unitEypes = "760"; } public function clone(){} }실행 결과는 다음과 같습니다
Eye 색상: red
Wing Beats/초: 220Eye 단위: 760
성별: 남성짝짓기: trueEye 색상: 빨간색Wing Beats/초: 220Eye 유닛: 760
성별: FEMAIL알 수: 186Eye 색상: 보라색
Wing Beats/초: 220Eye 유닛: 760성별: FEMAIL
계란 수: 92
프로토타입 모드에서는 고객이 복제 과정을 통해 특정 프로토타입을 사용하게 됩니다. 이 디자인 과정에서는 복제가 프로토타이핑의 핵심 요소이기 때문에 고객이 복제를 완료하는 데 참여합니다. , 따라서 고객은 단순한 요청 클래스가 아닌 기본 참여자입니다.
현대 기업 조직
창의적 디자인 패턴 측면에서 현대 기업 조직은 프로토타입 구현에 매우 적합합니다. 오늘날 기업 조직은 복잡하고 거대합니다. 계층적 구조와 마찬가지로 많은 공통 특성을 모델링해야 합니다. 이제 예를 통해 소프트웨어 엔지니어링 회사를 설명합니다.
소프트웨어 엔지니어링 회사는 전형적인 현대 조직으로, 제품 제작을 담당합니다. , 관리 부서(Management)는 리소스 조정 및 구성을 담당하고 마케팅 부서(Marketing)는 제품 판매, 홍보 및 전반적인 마케팅을 담당합니다.
인터페이스의 캡슐화
在这个原型实现中,首先为程序的接口(一个抽象类)增加OOP,与所有原型接口一样,这个接口包含一个克隆操作.另外它还包含一些抽象和具体的获取方法和设置方法.其中有一个抽象获取方法/设置方法对,但要由3个具体原型实现为这个抽象获取方法/设置方法对提供具体实现.其他获取方法和设置方法分分别应用于员工名,ID码和照片等属性.注意所有这些属性都是保护属性(protected),所以尽管具体的获取方法和设置方法有公共可见性,但由于操作中使用的属性具有保护和可见性,这就提供了某种程度的封装:
<?php abstract class IAcmePrototype { protected $name; protected $id; protected $employeePic; protected $department; //部门 abstract function setDept($orgCode); abstract function getDept(); //名字 public function setName($emName) { $this->name = $emName; } public function getName() { return $this->name; } //ID public function setId($emId) { $this->id = $emId; } public function getId() { return $this->id; } //雇员图像 public function setPic($ePic) { $this->employeePic = $ePic; } public function getPic() { return $this->employeePic; } abstract function clone(); }
利用这些获取方法和设置方法, 所有属性的值都通过继承的保护变量来设置.采用这种设计, 扩展类及其实例可以得到更好的封装.
接口实现
3个IAcmePrototype子类都必须实现"dept"抽象方法以及clone()
方法.类似地, 每个具体原型类还包含一个常量UNIT,它提供一个赋值,可以由实例(包括克隆的对象)作为标识
首先来看市场部的Marketing类:
Marketing.php
<?php include_once('IAcmePrototype.php'); class Marketing extends IAcmePrototype { const UNIT = "Marketing"; private $sales = "sales"; private $promotion = "promotion"; private $strategic = "strategic planning"; public function setDept($orgCode) { switch($orgCode) { case 101: $this->department = $this->sales; break; case 102: $this->department = $this->promotion; break; case 103: $this->department = $this->strategic; break; default : $this->department = "未识别的市场部"; } } public function getDept() { return $this->department; } public function clone() {} }
setDept()
方法的实现使用了一个参数.并不是直接输入市场部的部门,这个方法的参数是一个数字码, 通过一个switch语句,限制了3种可接受的情况和默认情况,别外两个原型实现也类似
Management.php
<?php include_once('IAcmePrototype.php'); class Management extends IAcmePrototype { const UNIT = "Management"; private $research = "research"; private $plan = "planning"; private $operations = "operations"; public function setDept($orgCode) { switch($orgCode) { case 201: $this->department = $this->research; break; case 202: $this->department = $this->plan; break; case 203: $this->department = $this->operations; break; default : $this->department = "未识别的管理部"; } } public function getDept() { return $this->department; } public function clone() {} }
Engineering.php
<?php include_once('IAcmePrototype.php'); class Engineering extends IAcmePrototype { const UNIT = "Engineering"; private $development = "development"; private $design = "design"; private $sysAd = "system administration"; public function setDept($orgCode) { switch($orgCode) { case 301: $this->department = $this->development; break; case 302: $this->department = $this->design; break; case 303: $this->department = $this->sysAd; break; default : $this->department = "未识别的工程部"; } } public function getDept() { return $this->department; } public function clone() {} }
以上这3个具体原型实现分别有其特定用途,不过它们都符合接口,可以创建各个原型实现的一个实例, 然后根据需要克隆多个实例.这个克隆的工作由Client类完成
客户
客户的设置非常简单: 分别创建各个具体原型的一个实例, 然后按以下列表来克隆各个实例:
市场部门实例:
-----市场部门克隆
-----市场部门克隆
管理部门实例
-----管理部门克隆
工程部门实例
-----工程部门克隆
-----工程部门克隆
将来只使用这些克隆对象.使用获取方法和设置方法将各个特定情况的信息赋给这些克隆对象.以下是Client的实现
Client.php
<?php function autoload($class_name) { include_once $class_name.'.php'; } class Client { private $market; private $manage; private $engineer; public function construct() { $this->makeConProto(); $Tess = clone $this->market; $this->setEmployee($Tess, "Tess Smith" , 101, 'ts101-1234', 'tess.png'); $this->showEmployee($Tess); $Jacob = clone $this->market; $this->setEmployee($Jacob, "Jacob Jones" , 101, 'jj101-2234', 'jacob.png'); $this->showEmployee($Jacob); $Ricky = clone $this->manage; $this->setEmployee($Ricky, "Ricky Rodriguez" , 203, 'rr101-5634', 'ricky.png'); $this->showEmployee($Ricky); $Olivaia = clone $this->engineer; $this->setEmployee($Olivaia, "Olivaia Perez" , 302, 'op301-1278', 'olivia.png'); $this->showEmployee($Olivaia); $John = clone $this->engineer; $this->setEmployee($John, "John Jacson" , 101, 'jj301-14548', 'john.png'); $this->showEmployee($John); } private function makeConProto() { $this->market = new Marketing(); $this->manage = new Management(); $this->engineer = new Engineering(); } private function showEmployee(IAcmePrototype $employeeNow) { $px = $employeeNow->getPic(); echo "<img src=$px width='150' height='150' /><br />"; echo $employeeNow->getName().'<br />'; echo $employeeNow->getDept().':'.$employeeNow::UNIT.'<br />'; echo $employeeNow->getId().'<hr />'; } private function setEmployee(IAcmePrototype $employeeNow, $nm, $dp, $id, $px) { $employeeNow->setName($nm); $employeeNow->setDept($dp); $employeeNow->setId($id); $employeeNow->setPic($px); } } $worker = new Client();
解释:
客户Client的构造函数类包含3个私有属性, 用来分别实例化3个具体原型类. makeConPro()
方法生成必要的实例.
接下来,使用克隆技术创建一个"员工"实例.然后,这个实例向一个设置方法setEmployee()发送特定的实例信息,这个设置方法使用IAcmePrototype接口类型提示,不过需要说明, 它只对第一个参数使用类型提示,其他参数都没有类型提示, 并不要求它们派生自IAcmePrototype接口.克隆"员工"可以使用IAcmePrototype抽象类的所有设置方法以及具体原型类实现的setDept()方法.
要使用各个员工的数据,Client类可以使用继承的获取方法.以下是运行Client输出的结果
Tess Smith
sales:Marketing
ts101-1234
Jacob Jones
sales:Marketing
jj101-2234
Ricky Rodriguez
operations:Management
rr101-5634
Olivaia Perez
design:Engineering
op301-1278
John Jacson
未识别的工程部:Engineering
jj301-14548
可以根据需要增加更多的克隆, 而且只需要对具体原型类完成一次实例化.使用原型模式时, 并不是建立具体类的多个实例,而只需要一个类实例化和多个克隆.
完成修改,增加特性
要记住,最重要(可能也是最基本)的是, 设计模式允许开发人员修改和增补程序,而不必一切从头开始.例如, 假设总裁决定公司增加一个新的部门,比如研究部门(Research), 这会很难吗?一点也不难.Research可以扩展IAcmePrototype抽象类, 然后实现抽象获取方法和设置方法来反映这个研究部门的组织.需要说明,Client类中获取方法和设置方法使用的代码提示指示一个接口,而不是一个抽象类的具体实现.所以, 只要增加的单元正确地实现了这个接口,就能顺利地增加到应用中, 而不会带来波动,也不需要对程序中的其他参与者进行重构.
보다 구체적인 수업을 추가할 수 있을 뿐만 아니라 개별 수업을 중단 없이 쉽게 수정할 수 있습니다. 예를 들어 이 조직의 마케팅 부서에서 기존 부서 외에 특별한 온라인 마케팅 부서가 필요하다고 결정했다고 가정해 보겠습니다. 이러한 방식으로 전환/케이스 작업에는 새 부서를 설명하는 새 분기(케이스)와 새 개인 속성(변수)이 필요합니다. 이 변경 사항은 다른 참가자에게 영향을 주지 않고 별도의 클래스에 고정됩니다. 손상을 일으키지 않을 것이며 애플리케이션의 규모가 클수록 이것이 더 중요하다는 것을 알 수 있습니다. 프로토타입 디자인 패턴은 일관성을 지원할 뿐만 아니라 유연한 변경도 지원한다는 것을 알 수 있습니다.
PHP 세계의 프로토타입
PHP는 서버 측 언어이고 MySQL 데이터베이스와 상호 작용하는 중요한 도구이므로 프로토타입 패턴은 특히 데이터베이스의 첫 번째 요소에 대해 별도의 객체를 생성하는 대신 PHP 프로토타입 패턴을 사용하여 생성할 수 있습니다. 구체적인 클래스의 인스턴스를 만든 다음 데이터베이스의 데이터를 사용하여 나머지 인스턴스(레코드)를 복제합니다.
복제 프로세스를 이해한 후 직접 인스턴스화 프로세스와 비교하면 다음과 같이 질문할 수 있습니다. " 즉, 복제에 개체를 직접 인스턴스화하는 것보다 더 적은 리소스가 필요한 이유는 무엇입니까? 차이점은 직접적으로 표시되지 않습니다. 개체가 복제를 통해 인스턴스화되면 생성자를 시작하지 않습니다. 복제본은 원본 클래스 속성을 모두 가져옵니다. 인스턴스화된 객체에 전달된 모든 값을 상속하는 것 외에도 생성자에 의해 생성되고 객체의 속성에 저장된 모든 값은 복제된 객체의 일부가 됩니다. 복제 객체는 생성자가 생성한 값에 액세스해야 하지만 액세스할 수 없다는 것은 인스턴스가 필요한 모든 정보를 갖고 이 데이터를 복제 객체에 전달할 수 있도록 클래스를 리팩터링해야 함을 의미합니다.
요약하면 프로토타입 모드는 다양한 유형의 PHP 프로젝트에 매우 적합합니다. 문제를 해결해야 하거나 모델을 만들어야 하는 경우 프로토타입 모드를 사용할 수 있습니다. 이 기사 외에 더 흥미로운 내용이 있을 것이므로 PHP 중국어 웹사이트에서 다른 관련 기사도 주목해 주세요!
추천 도서:
PHP OCP(폐쇄 원칙) 사용 사례 분석PHP 종속성 반전 사례에 대한 자세한 설명위 내용은 PHP 프로토타입 패턴 사례 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!