基础

子类没有定义构造方法,实例化时自动调用父类的构造方法

image.png

一个子类可以使用parent关键字访问父类,而不是用其类名
从当前类(不是子类)访问静态方法,属性,可以使用self,self指向当前类,就像伪变量$this指向当前类一样。

常量属性 使用关键词 const
const AVALIABLE = 0; // 常量不使用$开头,按惯例只能使用大写字母来命名。
常量属性只能通过类,不能通过类的示例访问
print ShopProduct::AVALIABLE;
image.png

大多数情况下抽象类至少包含一个抽象方法。

  1. <?php
  2. abstract class ShopProductWriter{
  3. protected $products = [];
  4. public function addProduct(ShopProduct $shopProduct){
  5. $this->products[] = $shopProduct;
  6. }
  7. abstract function writer();
  8. }

抽象类的每一个子类都必须实现抽象类的所有抽象方法或者把它们自身声明为抽象类,
子类方法访问权限不能低于父类的访问权限

接口
image.png

  1. <?php
  2. interface Chargeable{
  3. public function getPrice();
  4. public function getPrice2();
  5. }
  6. abstract class A implements Chargeable{
  7. }
  8. class B implements Chargeable{
  9. public function getPrice(){
  10. }
  11. public function getPrice2(){
  12. }
  13. }

任何实现接口的类都得实现接口中定义的所有方法,否则该类必修声明为abstract

image.png
image.png

拦截器
image.png

接口

  1. <?php
  2. class ShopProduct implements Chargeable{
  3. private $title;
  4. private $producerMainName;
  5. private $producerFirstName;
  6. protected $price;
  7. private $discount = 0;
  8. public function __construct($title, $firstName, $mainName, $price) {
  9. $this->title = $title;
  10. $this->producerFirstName = $firstName;
  11. $this->producerMainName = $mainName;
  12. $this->price = $price;
  13. }
  14. public function getProductFirstName(){
  15. return $this->producerFirstName;
  16. }
  17. public function getProductMainName(){
  18. return $this->producerMainName;
  19. }
  20. public function setDiscount($num){
  21. $this->discount = $num;
  22. }
  23. public function getDiscount(){
  24. return $this->discount;
  25. }
  26. public function getTitle(){
  27. return $this->title;
  28. }
  29. public function getPrice(){
  30. return ($this->price - $this->discount);
  31. }
  32. public function getProducer(){
  33. return "{$this->producerFirstName}" .
  34. "{$this->producerMainName}";
  35. }
  36. public function getSummeryLine(){
  37. $base = "{$this->title}({$this->producerFirstName}";
  38. $base .= "{$this->producerFirstName})";
  39. return $base;
  40. }
  41. }
  42. class CdShopProduct extends ShopProduct{
  43. private $playLength = 0;
  44. public function __construct( $title, $firstName, $mainName, $price, $playLength ) {
  45. parent::__construct( $title, $firstName, $mainName, $price );
  46. $this->playLength;
  47. }
  48. public function getPlayLength(){
  49. $this->playLength;
  50. }
  51. public function getSummeryLine() {
  52. $base = parent::getSummeryLine(); // TODO: Change the autogenerated stub
  53. $base .= ": playingtime - {$this->playLength}";
  54. return $base;
  55. }
  56. }
  57. class BookProduct extends ShopProduct{
  58. private $numPage = 0;
  59. public function __construct( $title, $firstName, $mainName, $price, $numPage ) {
  60. parent::__construct( $title, $firstName, $mainName, $price );
  61. $this->numPage = $numPage;
  62. }
  63. public function getNumberOfPage(){
  64. $this->numPage;
  65. }
  66. public function getSummeryLine() {
  67. $base = parent::getSummeryLine(); // TODO: Change the autogenerated stub
  68. $base .= ": page count - {$this->numPage}";
  69. }
  70. public function getPrice() {
  71. return $this->price; // TODO: Change the autogenerated stub
  72. }
  73. }
  74. abstract class ShopProductWriter{
  75. protected $products = [];
  76. public function addProduct(ShopProduct $shopProduct){
  77. $this->products[] = $shopProduct;
  78. }
  79. abstract function writer();
  80. }
  81. class XmlProductWriter extends ShopProductWriter {
  82. public function writer() {
  83. // TODO: Implement writer() method.
  84. var_dump($this->products);
  85. }
  86. }
  87. class TextProductWriter extends ShopProductWriter{
  88. public function writer() {
  89. // TODO: Implement writer() method.
  90. }
  91. }
  92. interface Chargeable{
  93. public function getPrice();
  94. }

抽象类

  1. <?php
  2. abstract class DomainObject{
  3. private $group;
  4. public function __construct() {
  5. $this->group = static::getGroup();
  6. }
  7. public static function create(){
  8. return new static();
  9. }
  10. static function getGroup(){
  11. return "default";
  12. }
  13. }
  14. class User extends DomainObject{
  15. }
  16. class Document extends DomainObject{
  17. static function getGroup() {
  18. return "document";
  19. }
  20. }
  21. class SpreadSheet extends Document {
  22. }
  23. //print_r(User::create());
  24. //print_r(SpreadSheet::create());

拦截器

  1. /***__get __set***/
  2. <?php
  3. class Person{
  4. private $_name;
  5. private $_age;
  6. function __get( $property ) {
  7. // TODO: Implement __get() method.
  8. $method = "get{$property}";
  9. if (method_exists($this, $method)) {
  10. return $this->$method();
  11. }
  12. return false;
  13. }
  14. function __set( $name, $value ) {
  15. // TODO: Implement __set() method.
  16. $method = "set{$name}";
  17. if (method_exists($this, $method)) {
  18. return $this->$method($value);
  19. }
  20. return false;
  21. }
  22. function getName(){
  23. return "Bob";
  24. }
  25. function getAge(){
  26. return "44";
  27. }
  28. function setName($name){
  29. $this->_name = $name;
  30. if (is_null($name)) {
  31. $this->_name = strtoupper($this->_name);
  32. }
  33. }
  34. function setAge($age){
  35. $this->_age = strtoupper($age);
  36. }
  37. }
  38. $person = new Person();
  39. print $person->Age;
  40. $person->name = "bob";
  41. var_dump($person);
  42. /////////////////////
  43. /**__call***/
  44. <?php
  45. class PersonWriter {
  46. function writeName(Person $p) {
  47. print $p->getName().'\n';
  48. }
  49. function writeAge(Person $p) {
  50. print $p->getAge().'\n';
  51. }
  52. }
  53. class Person {
  54. private $writer;
  55. function __construct(PersonWriter $writer) {
  56. $this->writer = $writer;
  57. }
  58. function __call( $methodname, $arguments ) {
  59. // TODO: Implement __call() method.
  60. if (method_exists($this->writer, $methodname)) {
  61. return $this->writer->$methodname($this);
  62. }
  63. }
  64. function getName() {
  65. return "Bob";
  66. }
  67. function getAge(){
  68. return 44;
  69. }
  70. }
  71. $person = new Person(new PersonWriter());
  72. $person->writeName(); // Bob

析构方法

  1. <?php
  2. # 析构方法
  3. class Person{
  4. private $name;
  5. private $age;
  6. private $id;
  7. function __construct($name, $age) {
  8. $this->name = $name;
  9. $this->age = $age;
  10. }
  11. function setId($id){
  12. $this->id = $id;
  13. }
  14. function __destruct() {
  15. // TODO: Implement __destruct() method.
  16. if (!empty($this->id)) {
  17. // 保存person数据
  18. print "saving person" . "\n";
  19. }
  20. }
  21. }
  22. $person = new Person("Martin", 54);
  23. $person->setId(12);
  24. unset($person); // 输出saving person

复制

  1. <php
  2. class CopyMe{}
  3. class CopyMe{}
  4. $first = new CopyMe();
  5. $second = $first; // 引用
  6. $third = clone $first; // 赋值
  7. var_dump($second === $first); // true
  8. var_dump($third === $first); // false

包含路径

把包放在include_path指向引用的目录,就可以在系统的任何地方被引用。

自动加载

call_user_func

image.png

反射

$prod_class = new ReflectionClass(‘CdShopProduct’);
Reflection::export($prod_class);

Class [ class CdShopProduct extends ShopProduct implements Chargeable ] {
@@ E:\WWW\test\php_obj\ShopProduct.php 60-77
- Constants [0] {
}
- Static properties [0] {
}
- Static methods [0] {
}
- Properties [2] {
Property [ private $playLength ]
Property [ protected $price ]
}
- Methods [10] {
Method [ public method __construct ] {
@@ E:\WWW\test\php_obj\ShopProduct.php 63 - 66
- Parameters [5] {
Parameter #0 [ $title ]
Parameter #1 [ $firstName ]
Parameter #2 [ $mainName ]
Parameter #3 [ $price ]
Parameter #4 [ $playLength ]
}
} …

image.png

多态

如果代码中存在大量条件语句,就说明需要多态
image.png

四个方向(避免)

  1. 代码重复
  2. 类知道太多
  3. 万能的类
  4. 条件语句

    UML 类图

    1 描述类
    image.png
    2 属性
    image.png
    访问控制
    image.png
    3 操作
    4 描述继承和实现
    image.png
    image.png

5 关联

image.png

image.png

image.png

6 聚合和组合
image.png

image.png

image.png

image.png

聚合 删除容器 被包含的对象可以归入另一个容器,而组合 删除容器,容器包含的对象也要被删除。

7 描述使用
image.png

image.png
image.png

8 使用注释
image.png

设计模式

组合与继承
使用组合
image.png

  1. <?php
  2. abstract class Lesson{
  3. private $duration;
  4. private $costStrategy;
  5. function __construct($duration, CostStrategy $strategy) {
  6. $this->duration = $duration;
  7. $this->costStrategy = $strategy;
  8. }
  9. function cost(){
  10. return $this->costStrategy->cost($this);
  11. }
  12. function chargeType(){
  13. return $this->costStrategy->chargeType();
  14. }
  15. function getDuration(){
  16. return $this->duration;
  17. }
  18. // Lesson 类的更多方法
  19. }
  20. class Lecture extends Lesson{
  21. // lecture 特定实现
  22. public function __construct( $duration, CostStrategy $strategy ) {
  23. parent::__construct( $duration, $strategy );
  24. }
  25. }
  26. class Seminar extends Lesson{
  27. public function __construct( $duration, CostStrategy $strategy ) {
  28. parent::__construct( $duration, $strategy );
  29. }
  30. }
  31. abstract class CostStrategy{
  32. abstract function cost(Lesson $lesson);
  33. abstract function chargeType();
  34. }
  35. class TimedCostStrategy extends CostStrategy{
  36. public function chargeType() {
  37. // TODO: Implement chargeType() method.
  38. return "hourly rate";
  39. }
  40. public function cost( Lesson $lesson ) {
  41. // TODO: Implement cost() method.
  42. return ($lesson->getDuration() * 5);
  43. }
  44. }
  45. class FixedCostStrategy extends CostStrategy{
  46. public function cost( Lesson $lesson ) {
  47. // TODO: Implement cost() method.
  48. return 30;
  49. }
  50. public function chargeType() {
  51. // TODO: Implement chargeType() method.
  52. return "fixed rare";
  53. }
  54. }
  55. $lessons[] = new Seminar(4, new TimedCostStrategy());
  56. $lessons[] = new Lecture(4, new FixedCostStrategy());
  57. foreach ($lessons as $lesson) {
  58. print "lesson change {$lesson->cost()} ";
  59. print "charge type {$lesson->chargeType()}\n";
  60. }
  61. ======输出======
  62. lesson change 20 charge type hourly rate
  63. lesson change 30 charge type fixed rare

降低耦合
image.png

  1. <?php
  2. class RegistrationMgr{
  3. function register(Lesson $lesson){
  4. // 处理该课程
  5. // 通知某人
  6. $notifier = Notifier::getNotifier();
  7. $notifier->inform("new lesson cost ({$lesson->cost()})");
  8. }
  9. }
  10. abstract class Notifier{
  11. static function getNotifier(){
  12. // 根据匹配或其他逻辑获得具体的类
  13. if (1 == rand(1, 2)) {
  14. return new MailNotifier();
  15. } else {
  16. return new TextNotifier();
  17. }
  18. }
  19. abstract function inform($message);
  20. }
  21. class MailNotifier extends Notifier{
  22. public function inform( $message ) {
  23. // TODO: Implement inform() method.
  24. print "Mail notification: {$message}\n";
  25. }
  26. }
  27. class TextNotifier extends Notifier{
  28. public function inform( $message ) {
  29. // TODO: Implement inform() method.
  30. print "Text notification: {$message}\n";
  31. }
  32. }
  33. $lessons1 = new Seminar(4, new TimedCostStrategy());
  34. $lessons2 = new Lecture(4, new FixedCostStrategy());
  35. $mgr = new RegistrationMgr();
  36. $mgr->register($lessons1);
  37. $mgr->register($lessons2);
  38. ====输出====
  39. Text notification: new lesson cost (20)
  40. Mail notification: new lesson cost (30)

针对接口编程,而不是针对实现编程

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: TF
  5. * Date: 2019/2/25
  6. * Time: 14:02
  7. */
  8. abstract class Employee{
  9. protected $name;
  10. function __construct($name) {
  11. $this->name = $name;
  12. }
  13. abstract function fire();
  14. }
  15. class Minion extends Employee{
  16. public function fire() {
  17. // TODO: Implement fire() method.
  18. print "{$this->name}: I'll clear my desk\n";
  19. }
  20. }
  21. class NastyBoss{
  22. private $employees = [];
  23. function addEmployee($employeeName){
  24. $this->employees[] = new Minion( $employeeName );
  25. }
  26. function projectFails(){
  27. if (count($this->employees) > 0) {
  28. $emp = array_pop($this->employees);
  29. $emp->fire();
  30. }
  31. }
  32. }
  33. $boss = new NastyBoss();
  34. $boss->addEmployee("tom");
  35. $boss->addEmployee("lucy");
  36. $boss->addEmployee("marry");
  37. $boss->projectFails(); // marry: I'll clear my desk

image.png

多态存在的三个必要条件
1 继承
2 重写
3 父类引用指向子类对象

单例模式

  1. <?php
  2. class Preference{
  3. private $props = [];
  4. private static $instance;
  5. private function __construct() {
  6. }
  7. public static function getInstance(){
  8. if (empty(self::$instance)) {
  9. self::$instance = new Preference();
  10. }
  11. return self::$instance;
  12. }
  13. public function setProperty($key, $val){
  14. $this->props[$key] = $val;
  15. }
  16. public function getProperty($key){
  17. return $this->props[$key];
  18. }
  19. }
  20. $pref = Preference::getInstance();
  21. $pref->setProperty("name", "marry");
  22. unset($pref); // 移除引用
  23. $pref2 = Preference::getInstance();
  24. print $pref2->getProperty("name") . "\n"; // 该属性值并未丢失

image.png

image.png

工厂方法模式

  1. <?php
  2. abstract class AppEncoder{
  3. abstract function encode();
  4. }
  5. class BloggsAppEncoder extends AppEncoder{
  6. public function encode() {
  7. // TODO: Implement encode() method.
  8. return 'b';
  9. }
  10. }
  11. class MegaAppEncoder extends AppEncoder{
  12. public function encode() {
  13. // TODO: Implement encode() method.
  14. return 'm';
  15. }
  16. }
  17. abstract class CommsMannager{
  18. abstract function getHeaderText();
  19. abstract function getAppEncoder();
  20. abstract function getFooterText();
  21. }
  22. class BloggsCommsMannager extends CommsMannager {
  23. public function getAppEncoder() {
  24. // TODO: Implement getAppEncoder() method.
  25. return new BloggsAppEncoder();
  26. }
  27. public function getFooterText() {
  28. // TODO: Implement getFooterText() method.
  29. return "blogs footer\n";
  30. }
  31. public function getHeaderText() {
  32. // TODO: Implement getHeaderText() method.
  33. return "blogs header\n";
  34. }
  35. }
  36. $bloggscomms = new BloggsCommsMannager();
  37. $bloggscomms->getAppEncoder();

image.png
image.png

image.png

image.png

抽象工厂模式

  1. <?php
  2. abstract class CommsManager{
  3. abstract function getHeaderText();
  4. abstract function getAppEncoder();
  5. abstract function getTtdEncoder();
  6. abstract function getContactEncoder();
  7. abstract function getFooterText();
  8. }
  9. abstract class ApptEncoder{
  10. abstract function encode();
  11. }
  12. abstract class TtdEncoder{
  13. abstract function encode();
  14. }
  15. abstract class ContactEncoder{
  16. abstract function encode();
  17. }
  18. //
  19. class BloggsApptEncoder extends ApptEncoder{
  20. public function encode() {
  21. // TODO: Implement encode() method.
  22. }
  23. }
  24. class BloggsTtdEncoder extends TtdEncoder{
  25. public function encode() {
  26. // TODO: Implement encode() method.
  27. }
  28. }
  29. class BloggsContactEncoder extends ContactEncoder{
  30. public function encode() {
  31. // TODO: Implement encode() method.
  32. }
  33. }
  34. class BloggsCommsManager{
  35. public function getHeaderText(){
  36. return "header\n";
  37. }
  38. public function getAppEncoder(){
  39. return new BloggsApptEncoder();
  40. }
  41. public function getTtdEncoder(){
  42. return new BloggsTtdEncoder();
  43. }
  44. public function getContactEncoder(){
  45. return new BloggsContactEncoder();
  46. }
  47. public function getFooterText(){
  48. return "footer\n";
  49. }
  50. }

image.png

image.png

image.png

  1. <?php
  2. abstract class CommsMannager{
  3. const APPT = 1;
  4. const TTD = 2;
  5. const CONTACT = 3;
  6. abstract function getHeaderText();
  7. abstract function make($flag_int);
  8. abstract function getFooterText();
  9. }
  10. abstract class ApptEncoder{
  11. abstract function encode();
  12. }
  13. abstract class TtdEncoder{
  14. abstract function encode();
  15. }
  16. abstract class ContactEncoder{
  17. abstract function encode();
  18. }
  19. //
  20. class BloggsApptEncoder extends ApptEncoder{
  21. public function encode() {
  22. // TODO: Implement encode() method.
  23. }
  24. }
  25. class BloggsTtdEncoder extends TtdEncoder{
  26. public function encode() {
  27. // TODO: Implement encode() method.
  28. }
  29. }
  30. class BloggsContactEncoder extends ContactEncoder{
  31. public function encode() {
  32. // TODO: Implement encode() method.
  33. }
  34. }
  35. class BloggsCommsManager extends CommsMannager{
  36. public function getHeaderText() {
  37. // TODO: Implement getHeaderText() method.
  38. }
  39. public function make($flag_int) {
  40. // TODO: Implement getAppEncoder() method.
  41. switch ($flag_int) {
  42. case self::APPT:
  43. return new BloggsApptEncoder();
  44. break;
  45. case self::CONTACT:
  46. return new BloggsContactEncoder();
  47. break;
  48. case self::TTD:
  49. return new BloggsTtdEncoder();
  50. break;
  51. }
  52. }
  53. public function getFooterText() {
  54. // TODO: Implement getFooterText() method.
  55. return "footer";
  56. }
  57. }

原型模式

image.png
image.png

image.png

  1. <?php
  2. // 海
  3. class Sea{
  4. }
  5. // 平原
  6. class Plains{
  7. }
  8. // 森林
  9. class Forest{
  10. }
  11. /**地球的海,平原,森林**/
  12. class EarthSea extends Sea{
  13. }
  14. class EarthPlains extends Plains{
  15. }
  16. class EarthForest extends Forest{
  17. }
  18. /**火星的海,平原,森林**/
  19. class MarsSea extends Sea{
  20. }
  21. class MarsPlains extends Plains{
  22. }
  23. class MarsForest extends Forest{
  24. }
  25. // 抽象工厂 原型模式
  26. class TerrainFactory{
  27. private $sea;
  28. private $plains;
  29. private $forest;
  30. function __construct(Sea $sea, Plains $plains, Forest $forest) {
  31. $this->sea = $sea;
  32. $this->plains = $plains;
  33. $this->forest = $forest;
  34. }
  35. function getSea(){
  36. return clone $this->sea;
  37. }
  38. function getPlains(){
  39. return clone $this->plains;
  40. }
  41. function getForest(){
  42. return clone $this->forest;
  43. }
  44. }
  45. $factory = new TerrainFactory(new EarthSea(), new MarsPlains(), new EarthForest());
  46. print_r($factory->getSea());
  47. print_r($factory->getPlains());
  48. print_r($factory->getForest());
  49. // 地球
  50. //class EarthTerrainFactory extends TerrainFactory{
  51. // public function getForest() {
  52. // // TODO: Implement getForest() method.
  53. // }
  54. // public function getPlains() {
  55. // // TODO: Implement getPlains() method.
  56. // }
  57. // public function getSea() {
  58. // // TODO: Implement getSea() method.
  59. // }
  60. //}
  61. //
  62. //// 火星
  63. //class MarsTerrainFactory extends TerrainFactory{
  64. // public function getSea() {
  65. // // TODO: Implement getSea() method.
  66. // }
  67. // public function getPlains() {
  68. // // TODO: Implement getPlains() method.
  69. // }
  70. // public function getForest() {
  71. // // TODO: Implement getForest() method.
  72. // }
  73. //}

image.png

  1. <?php
  2. // 如果产品对象引用了其他对象,应该实现__clone()方法 确保得到的是深复制
  3. class Contained{}
  4. class Container{
  5. public $contained;
  6. public function __construct() {
  7. $this->contained = new Contained();
  8. }
  9. public function __clone() {
  10. // TODO: Implement __clone() method.
  11. // 确保被克隆的对象持有的是self::$contained的克隆而不是引用
  12. $this->contained = clone $this->contained;
  13. }
  14. }
  15. $c = new Container();
  16. var_dump($c->contained);
  1. <?php
  2. Setting.php
  3. class Settings{
  4. static $COMMSTYPE = 'Bloggs';
  5. }
  6. _______________
  7. require_once "Setting.php";
  8. class Appconfig{
  9. private static $instance;
  10. private $commsManager;
  11. private function __construct() {
  12. // 仅运行一次
  13. $this->init();
  14. }
  15. private function init(){
  16. switch (Settings::$COMMSTYPE) {
  17. case 'Mega':
  18. $this->commsManager = new MegaCommsManager();
  19. break;
  20. default:
  21. $this->commsManager = new BloggsCommsMannager();
  22. }
  23. }
  24. public static function getInstance(){
  25. if (empty(self::$instance)) {
  26. self::$instance = new self();
  27. }
  28. return self::$instance;
  29. }
  30. public function getCommsManager(){
  31. return $this->commsManager;
  32. }
  33. }

image.png

  1. $commsMgr = Appconfig::getInstance()->getCommsManager();
  2. $commsMgr->getAppEncorder()->encode();

组合

组合优于继承