关于三种工厂模式的总结

工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。本文对这三种模式进行了介绍并且分析它们之间的区别。

简单工厂模式

简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码逻辑将会非常复杂。

<?php

//简单工厂方法

interface People
{
    public function say();

}

class Man implements People
{
    public function say()
    {
        echo 'this is a man ';
    }
}

class Women implements People
{
    public function say()
    {
        echo 'this is a women';
    }
}

class SimpleFactory
{
    public static function create($name)
    {
    if ($name == 'man') {
            return new Man();
        } elseif ($name == 'women') {
            return new Women();
        }
    }

}

//具体调用
$man = SimpleFactory::create('man');
$man->say();
$women = SimpleFactory::create('women');
$women->say();

简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。

工厂方法模式

此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。这样做的好处是核心类只关注工厂类的接口定义,而具体的产品实例交给具体的工厂子类去创建。当系统需要新增一个产品是,无需修改现有系统代码,只需要添加一个具体产品类和其对应的工厂子类,使系统的扩展性变得很好,符合面向对象编程的开闭原则。体代码如下:

<?php
//工厂方法模式

interface People
{
    public function say();
}

class Man implements People
{
    public function say()
    {
        echo 'this is a man';
    }
}

class Women implements People
{
    public function say()
    {
        echo 'this is a women';
    }
}

//与简单工厂模式相比。区别在于,此处将对象的创建抽象成一个接口
interface CreatePeople
{
    public function create();
}

class FactoryMan implements CreatePeople
{
    public function create()
    {
        return new Man();
    }

}

class FactoryWomen implements CreatePeople
{
    public function create()
    {
        return new Women();
    }
}

class  Client
{
    // 具体生产对象并执行对象方法测试
    public function test() {
        $factory = new FactoryMan();
        $man = $factory->create();
        $man->say();

        $factory = new FactoryWomen();
        $man = $factory->create();
        $man->say();
    }
}

// 执行
$demo = new Client();
$demo->test();

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

此模式是对工厂方法模式的进一步扩展。在工厂方法模式中,一个具体的工厂负责生产一类具体的产品,即一对一的关系,但是,如果需要一个具体的工厂生产多种产品对象,那么就需要用到抽象工厂模式了。

<?php 

interface TV{
  public function open();
  public function watch();
}

class HaierTv implements TV
{
  public function open()
  {
      echo "Open Haier TV <br>";
  }

  public function watch()
  {
      echo "I'm watching TV <br>";
  }
}

interface PC{
  public function work();
  public function play();
}

class LenovoPc implements PC
{
  public function work()
  {
      echo "I'm working on a Lenovo computer <br>";
  }
  public function play()
  {
      echo "Lenovo computers can be used to play games <br>";
  }
}

abstract class Factory{
  abstract public static function createPc();
  abstract public static function createTv();
}

class ProductFactory extends Factory
{
  public static function createTV()
  {
      return new HaierTv();
  }
  public static function createPc()
  {
      return new LenovoPc();
  }
}

$newTv = ProductFactory::createTV();
$newTv->open();
$newTv->watch();

$newPc = ProductFactory::createPc();
$newPc->work();
$newPc->play();

在上面的Factory抽象类中,定义了两个抽象方法,这两个抽象方法分别用来生产不同的产品(即由不同类实例化的对象)。

工厂方法模式和抽象工厂模式对比

通过以上代码:我们来对比一下工厂方法模式和抽象工厂模式:

  • 工厂方法模式中

当我需要多生产一种新的产品,比如factoryKid这个产品,我需要专门再设一个factoryKid的工厂,即添加如下代码:

class Kid implements People{
    public function say()
    {
        echo 'this is a kid';
    }
}

class FactoryKid implements CreatePeople
{
    public function create()
    {
        return new Kid();
    }
}
  • 抽象工厂模式中

同样当我需要多生产一种新的产品,比如生产一个iphone,此时我需要修改工厂父类里的接口,并且在具体工厂类ProductFactory这个工厂里增加一条createPhone生产线(即类里面的方法),所需添加的代码如下:

interface Phone{
  public function work();
  public function sms();
}

class IPhone implements Phone
{
  public function work()
  {
      echo "I'm iphone <br>";
  }
  public function sms()
  {
      echo "this is an iphone <br>";
  }
}
//在原来的抽象工厂类中添加方法声明
abstract class Factory{
    abstract public static function createPc();
    abstract public static function createTv();
    abstract public static function createPhone();
}

//在原来的工厂类里添加一个方法
class ProductFactory extends Factory
{
  public static function createTV()
  {
      return new HaierTv();
  }
  public static function createPc()
  {
      return new LenovoPc();
  }
  public static function createPhone()
  {
      return new IPhone();
  }
}

从上面的分析可以看出,要生产一个新的产品,抽象工厂模式并不比工厂方法模式更为便捷,那么抽象工厂模式的好处在哪呢?它优点就是在于是增加固定类型产品的不同具体工厂比较方便,比如我要增加一个生产同样类型产品的具体工厂Product2Factory,那么就再建一个Product2Factory类继承Factory就可以了。

最后的最后,总结一下工厂方法模式和抽象工厂模式的核心区别
  • 工厂方法模式利用继承,抽象工厂模式利用组合
  • 工厂方法模式产生一个对象,抽象工厂模式产生一族对象
  • 工厂方法模式利用子类创造对象,抽象工厂模式利用接口的实现创造对象

原文发布于微信公众号 - 编码前线(gh_acef1225aadd)

原文发表时间:2018-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏工科狗和生物喵

【计算机本科补全计划】《C++ Primer》:类型转换

正文之前 学习,不如爆文?反正晚上也不会学习,某个家伙也对我爱理不理的!!!!(这才是最骚的吧),刚好欠了 C++ Primer太多烂账了。不如赶紧还了! 对了...

3108
来自专栏阮一峰的网络日志

undefined与null的区别

大多数计算机语言,有且仅有一个表示"无"的值,比如,C语言的NULL,Java语言的null,Python语言的None,Ruby语言的nil。 有点奇怪的是,...

3084
来自专栏AzMark

Python字符串

1555
来自专栏程序员互动联盟

【编程基础】C++ Primer快速入门五:实用的模板库

除上篇博客介绍的基本数据类型外,C++ 还定义了一个内容丰富的抽象数据类 型标准库。包括 string 和 vector,它们分别定义了字符串和矢量(集合)。s...

2935
来自专栏pangguoming

全面理解面向对象的 JavaScript

前言 当今 JavaScript 大行其道,各种应用对其依赖日深。web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而...

38110
来自专栏Android机动车

设计模式——工厂方法模式

工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

802
来自专栏转载gongluck的CSDN博客

python笔记:#007#变量

变量的基本使用 程序就是用来处理数据的,而变量就是用来存储数据的 目标 变量定义 变量的类型 变量的命名 01. 变量定义 在 Python 中,每个变量 在...

3338
来自专栏desperate633

设计模式之工厂方法模式(FACTORY METHOD)问题模拟工厂方法模式分析依赖倒置原则小结

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。 我们依然接着简单工厂模式提出的披萨店问题继续探讨

974
来自专栏女程序员的日常

虚函数&多态

对于经常被问到的虚函数和多态的问题,发现百度百科回答得十分详细,所以自己在百度百科上的解释进行总结 一、虚函数 (1)虚函数简介:在某基类中声明为virtua...

2321
来自专栏编程

关于python字典类型最疯狂的表达方式

[译]关于python字典类型最疯狂的表达方式 一个Python字典表达式谜题 这个子字典是从哪里来的 Umm..好吧,可以得到什么结论呢? 一篇来自 Dan ...

21110

扫码关注云+社区

领取腾讯云代金券