35

开发人员的工厂方法模式

 5 years ago
source link: http://www.apexyun.com/kai-fa-ren-yuan-de-gong-han-fang-fa-mo-shi/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

开发人员的工厂方法模式

www.apexyun.comnullJanessa Tran BlockedUnblockFollow关注3月24日

uA3qe2M.jpg!web

在上一篇文章中,我们概述了 设计模式 的定义,它们的类别以及它们在软件开发中的重要性。在本文中,让我们深入探讨第一个被广泛使用的名为" 工厂方法模式"的 设计模式。

什么是工厂方法模式?

工厂方法模式(或简称为工厂模式)是一种创建模式,它使用工厂方法来处理创建对象的问题,而无需指定将要创建的对象的确切类。这是通过调用工厂方法创建对象来完成的,该方法在接口中指定并由子类实现,或者在基类中实现并可选地由派生类覆盖 - 而不是通过调用构造函数。

问题

想象一下,您是一个名为LogisticsApp的物流管理应用程序的创建者。您的应用程序的第一个版本只能通过卡车处理运输,因此您当前的大部分代码都在Truck类中。

过了一段时间,您的应用程序在物流社区变得非常受欢迎。每天您都会收到海运公司提出的数十项要求,将海运物流纳入您的应用程序。

作为LogisticsApp的创建者,您对目前的成功感到非常满意。但是,在考虑将海运物流代码纳入您的应用程序的方法时,您突然意识到有许多问题等待解决。

目前,最大的问题是您当前的大部分代码已经与 Truck 类相关联。将 Ship 类添加到应用程序中需要对整个代码库进行更改。此外,如果您以后决定向应用添加其他类型的传输,则可能需要再次进行所有这些更改。 3q6bmmm.png!web 目前,为程序添加一个新类是一个很大的问题,因为其余代码已经耦合到Truck类

幸运的是,有一种设计模式可以帮助您解决这个问题,即工厂方法模式。根据其定义,工厂方法模式建议您使用特殊工厂方法调用替换直接对象构造调用(使用new运算符)。实际上,仍然通过new运算符创建对象,但是它是从工厂方法中调用的。工厂方法返回的对象通常称为 "产品"。

乍一看,这种变化可能看起来毫无意义:我们只是将构造函数调用从程序的一部分移动到另一部分。但是,请考虑这一点:现在您可以覆盖子类中的工厂方法并更改方法创建的产品类。

结构体

工厂方法模式的结构由4个重要组成部分组成:产品,混凝土产品,创造者和混凝土创造者。 Mv67ZvQ.png!web 工厂方法模式的结构

  • Product 声明了接口,该接口对于创建者及其子类可以生成的所有对象是通用的。
  • Concrete Products是产品界面的不同实现。
  • Creator类声明返回新产品对象的工厂方法。重要的是此方法的返回类型与产品界面匹配。
  • Concrete Creators覆盖基础工厂方法,因此它返回不同类型的产品。

请注意,工厂方法不必 始终 创建 新实例。它还可以从缓存,对象池或其他源返回现有对象。

何时使用工厂方法模式?

工厂方法模式在以下情况下真正发挥作用:

  • 不要提前知道你需要什么类对象。
  • 您希望将产品创建代码集中到程序中的一个位置,使代码更易于支持和交互。
  • 想要封装对象创建,并且不希望用户必须知道每个子类。

物流应用问题的解决方案

让我们使用工厂方法模式来解决将海运物流纳入您的LogisticsApp的问题。

我们可以看到卡车和船舶有以下相似之处:

  • 它们是不同类型的运输工具
  • 他们都提供了一些东西

考虑到这一点,我们将创建一个名为 Transport 的接口,它将提供 deliver() 方法。

<?php interface Transport { public function deliver(): string; } ?>`

接下来,让我们创建两个名为Truck and Ship的具体产品类。这些类都实现了 Transport 接口,因此它们都必须覆盖 deliver 方法。

<?php class Truck implements Transport { public function deliver(): string { return "Truck: Deliver by land in a box."; } }`
class Ship implements Transport { public function deliver(): string { return "Ship: Deliver by sea in a container."; } } ?>`

a6vYZfN.png!web

之后,让我们创建一个名为 Logistics 的创建者类,这个类的主要职责是提供 createTransport() ---一个返回与 Transport 接口匹配的对象的抽象方法。它的定义将由具体的创建者类提供。

<?php abstract class Logistics { public function planDelivery(string $transportType): string { $transport = $this->createTransport($transportType); echo $transport->deliver();`
 } abstract public function createTransport(string $transporType): Transport; } ?>`

最后,让我们创建两个名为 RoadLogisticsSeaLogistics的 具体创建者类:

<?php class RoadLogistics extends Logistics { public function createTransport(string $transportType) { if(strtolower($transportType) === strtolower("Truck")) { return new Truck; } } }`
class SeaLogistics extends Logistics { public function createTransport(string $transportType) { if(strtolower($transportType) === strtolower("Ship")) { return new Ship; } } } ?>`

而已!我们已完成为LogisticsApp设置工厂方法模式。让我们执行下面的代码来查看最终结果:

$roadLogistics = new RoadLogistics; $seaLogistics = new SeaLogistics;`
$transport = $roadLogistics->planDelivery("Truck"); $transport->delivery();`
echo "\n";`
$transport = $seaLogistics->planDelivery("Ship"); $transport->delivery();`

结果:

Truck: Deliver by land in a box. Ship: Deliver by sea in a container.`

现在,使用工厂方法的代码(通常称为客户端代码)看不到各个子类返回的实际产品之间的差异。客户端将所有产品视为抽象 传输 。物流运输的类型(RoadLogistics,SeaLogistics)将决定将使用的确切运输类型。因此,现在您可以根据需要添加任意数量的新传输类型,而无需无意中影响现有代码库。真棒! = d

工厂方法模式的利弊

优点

  • 工厂方法模式有助于防止创建者与具体产品之间的紧密耦合。
  • 使用工厂方法模式,您可以将产品创建代码集中到程序中的一个位置,使代码更易于支持和交互。
  • 通过使用工厂方法模式,您可以在不破坏现有客户端代码的情况下将新类型的产品引入程序。

缺点

  • 代码可能会变得更加复杂,因为您需要引入许多新的子类来实现该模式。

结论

在本文中,我们学到了很多关于工厂方法模式的知识。我希望这种设计模式将成为未来某个软件开发问题的完美解决方案。

在本系列的下一篇文章中,我们将了解一个名为Abstract Factory Pattern的Factory Method Pattern的兄弟。敬请关注! = d

查看英文原文

查看更多文章

公众号:银河系1号

联系邮箱:[email protected]

(未经同意,请勿转载)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK