通过克隆生成对象

原型是抽象工厂的另一种变化形式,它也叫克隆模式,具体产品类会变成生成它们自身的基础。它和抽象工厂一样,也是创建对象。不过它是使用clone的方式进行创建。

优点:

减少了重复的new操作,因为实例化一个对象是需要很大开销的,每次创建新实例都会重新初始化
原型模式是先创建好对象,再对其进行克隆,免去了重复初始化操作,系统只需要拷贝内存

缺点:

每个具体产品类必须要包 clone 方法
对已知的产品类进行改造起来非常麻烦
拿生活中的例子来举例,孙悟空的毛一吹就可以变化成很多的猴子猴孙,这就好比使用了原型模式。还有我们小时候玩过的红色警戒,我们可以通过兵工厂来制造出许多坦克、士兵等等

复杂实现:

Prototype.png

  1. // 兵工厂
  2. abstract Munition
  3. {
  4. abstract launch():string;
  5. }
  6. // 战车工厂
  7. abstract WarChariot
  8. {
  9. abstract launch():string;
  10. }
  11. // 具体产品:动员兵
  12. class SovietSoldier extends Munition
  13. {
  14. public function launch(): string
  15. {
  16. return '攻击!';
  17. }
  18. public function __clone()
  19. {
  20. // do something
  21. }
  22. }
  23. // 具体产品:美国大兵
  24. class AmericaSoldier extends Munition
  25. {
  26. public function launch(): string
  27. {
  28. return '攻击!';
  29. }
  30. public function __clone()
  31. {
  32. // do something
  33. }
  34. }
  35. // 具体产品:犀牛坦克
  36. class SovietTank extends WarChariot
  37. {
  38. public function launch(): string
  39. {
  40. return '攻击!';
  41. }
  42. public function __clone()
  43. {
  44. // do something
  45. }
  46. }
  47. // 具体产品:盟军坦克
  48. class AmericaTank extends WarChariot
  49. {
  50. public function launch(): string
  51. {
  52. return '攻击!';
  53. }
  54. public function __clone()
  55. {
  56. // do something
  57. }
  58. }
  1. class Factory
  2. {
  3. public Munition $munition;
  4. public WarChariot $WarChariot;
  5. public function __construct(Muniton $muntion,WarChariot $warChariot)
  6. {
  7. $this->munition = $muntion;
  8. $this->munition = $warChariot;
  9. }
  10. // 创建各种士兵
  11. public function createMunition(): Munition
  12. {
  13. return $this->munition;
  14. }
  15. // 创建各种坦克
  16. public function createWarChariot: WarChariot
  17. {
  18. return $this->warChariot;
  19. }
  20. }
  1. $factory = new Factory(
  2. new SovietSoldier(),
  3. new SovietTank(),
  4. )
  5. // 创建士兵
  6. $factory->createMunition()->launch();
  7. // 创建坦克
  8. $factory->createWarChariot()->launch();

总结:

原型模式的好处是,它不需要像工厂方法模式或抽象方法模式那样每次加入新的产品家族时,都要为产品创建相关的具体创建者类。减少了代码量