工程模式和抽象工厂模式_功能工厂模式

工程模式和抽象工厂模式

您是否需要一种非常快速的方法来制作Factory对象? 然后,您需要lambda或其他函数传递! 它不仅快速,而且非常简单。 我敢打赌,如果您对Lambdas相当满意,那么您只需阅读标题就可以做到这一点。 如果您是其中之一,请坚持; 你永远不知道你能学到什么。

附带说明:我正在用Java和Python做代码示例。 为什么? 因为我喜欢这两种语言,所以为这两种语言放东西肯定不会受到伤害。

工厂模式入门

如果您已经知道什么是工厂设计模式,则可以跳到下一部分。

Factory模式的重点是为对象和方法提供一种实例化对象的方法,而无需暴露所有(或通常是任何一种 )实例化逻辑(需要将什么传递到构造函数中)。

举一个愚蠢的例子,假设有一类“ Scientist ,它需要一种方法来产生新的Pen来写下实验数据,但是他不想被创建过程所困扰。 为此,您将为Scientist一个PenFactoryScientist只需知道按一下工厂的按钮即可获得新的笔。

PenFactory是一个简单的对象,只有一个create()方法,该方法在您每次调用Pen时都会提供一个新的Pen实例。 如果Scientist关心Pen颜色,则可以为他提供ColoredPenFactoryColoredPenFactorycreate()方法也接受颜色参数。 然后, ColoredPenFactory必须弄清楚如何为该笔提供这种颜色。

扩展工厂模式理念

Factory Pattern是面向对象代码的一种模式,因此仅限于OO的工作方式,但是我们可以利用其目的并尝试找到一种以功能方式使其实现的方法,这实际上使它成为了很多更轻松。

实际上,由于缺乏传递功能的能力而创建了许多OO设计模式。 这些中的大多数都可以简单地通过传递函数来替换。 其中的简短列表包括命令,工厂和策略。 如果其他许多人接受函数,则可以删除许多类层次结构。 其中一些包括模板和访客。

因此,最大的区别是工厂类不必是一个类。 它也可以是简单的“可调用”。 因此,让我们深入研究一些示例。

OO笔厂

这样您就可以看到经典的OO模式和新的功能模式之间的区别,这里是OO Java中的示例类和接口。

public interface Pen {void write(String toWrite);boolean outOfInk();
}public interface PenFactory {Pen create();
}public class Scientist {private PenFactory penerator;private Pen pen;public Scientist(PenFactory penerator) {this.penerator = penerator;this.pen = penerator.create();}public void writeData(String data) {if(pen.outOfInk()) {pen = penerator.create();}pen.write(data);}
}

在OO Python中

class Pen(metaclass=ABCMeta):def write(self, text):passdef out_of_ink(self):passclass PenFactory(metaclass=ABCMeta):def create(self):passclass Scientist():def __init__(self, pen_factory):self.penerator = pen_factoryself.pen = self.penerator.create()def write_data(self, data):if self.pen.out_of_ink():pen = self.penerator.create()pen.write(data)

您是否了解我如何称呼PenFactory实例penerator ? 我认为这有点愚蠢。 希望您也喜欢。 如果没有,哦。

转换为简单的功能模式

当涉及到Java版本时,由于PenFactory视为功能接口,因此实际上不需要进行任何更改,但是由于您可以用Supplier<Pen>替换PenFactory任何实例, PenFactory不需要它。 因此, Scientist类看起来像这样:

public class Scientist {private Supplier penerator;private Pen pen;public Scientist(Supplier penerator) {this.penerator = penerator;this.pen = penerator.get();}public void writeData(String data) {if(pen.outOfInk()) {pen = penerator.get();}pen.write(data);}
}

在Python中,您可以完全删除PenFactory而只需使用返回Pen任何可调用对象即可。 您还必须在“ Scientist中更改调用工厂的create()方法的行,并仅用括号将其替换即可。

class Scientist():def __init__(self, pen_factory):self.penerator = pen_factoryself.pen = self.penerator()def write_report(self, data):if self.pen.out_of_ink():self.pen = self.penerator()self.pen.write(data)

因此,要创建带有提供MyPenClass实例的lambda的Scientist实例,请在Java中键入以下内容:

Scientist albert = new Scientist(() -> new MyPenClass());

或在Python中:

albert = Scientist(lambda: MyPenClass())
# or skip the lambda by passing the "constructor"
thomas = Scientist(MyPenClass)

具有依赖关系的类的工厂

假设我想为一个类的工厂制造工厂,该类的构造函数需要一个笔品牌的名称。 我们将此类BrandPen 。 我们将如何为之建立工厂? 好吧,写lambda并没有什么不同,真的。 但是,我们如何看待其他定义传入的可调用对象的方式呢?

在Java中,您可以将lambda的实例保存在变量中并传递给它。或者您可以使用方法引用:

Supplier bicPen = () -> new BrandPen("BiC");
Scientist thomas = new Scientist(bicPen);
// assuming that BrandPen has a static method called bicPen
Scientist nicola = new Scientist(BrandPen::bicPen);

在Python中,您可以定义一个执行该功能的函数或分配一个partial函数来执行此操作:

def bic_pen():return BrandPen("BiC")
# or
bic_pen = partial(BrandPen, "BiC")nicola = Scientist(bic_pen)

有依存关系的工厂

哦,天哪, Scientist现在希望能够指定工厂提供的笔的颜色 ! 好吧,您可以为他提供每种颜色的不同工厂,并告诉他使用每个不同的工厂来制造不同的笔,但是在他的实验室中根本没有足够的空间容纳这么多PenFactory ! 我们必须给工厂提供可以使用哪种颜色的信息。

为此,我们必须将Java的Supplier<Pen>更改为Function<>Color, Pen> 。 显然,您无需在Python中更改类型,因为它是动态的并且不需要类型信息。

但是, Scientist班也需要改变他们使用工厂的方式。 在Java中,无论Scientist在哪里请求新实例,都需要提供颜色,如下所示:

pen = penerator.apply(Color.RED);

或者像这样,在Python中:

self.pen = self.penerator(Color.RED)

我们传递给Java Scientist的工厂看起来像这样:

Scientist erwin = new Scientist(color -> new ColoredPen(color, "BiC"));

我们在Python中提供的代码如下所示:

def colored_bic_pen(color):return ColoredPen(color, "BiC")erwin = Scientist(colored_bic_pen)

多方法工厂

在Internet上“工厂模式”的一些示例中,它们显示了具有多种方法来调用生成对象的工厂。 我还没有在现实生活中看到这种效果,但是可能会发生。 在这些情况下,最好坚持使用OO选项,但是如果要将其更改为功能模式,只需提供单独的工厂可调用对象,而不是使用多个方法的一个对象即可。

奥托罗

我没想到会写那么多,但是随着我的前进,我想展示太多的小差异。 我没有了解所有内容,主要是因为我不想跟踪所有内容,尤其是两种语言,但是我敢肯定,我给了您足够的工具箱,可以在您的计算机上弄清楚它们拥有。

我希望你学到了一些东西。 如果没有,我希望您至少喜欢这个例子。

翻译自: https://www.javacodegeeks.com/2015/02/functional-factory-pattern.html

工程模式和抽象工厂模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言怎么输入3个数输出最大值

方法&#xff1a;首先使用scanf()接收从键盘输入的三个数&#xff1b;然后使用“if else”语句比较三个数的大小&#xff0c;获得最大值&#xff1b;最后使用print()函数将最大值输出即可。c语言输入3个数输出最大值#include int main() { // 输入abc输出最大值 int a; …

java调用ecdh_椭圆曲线ECC ECDH原理 javacard实现

椭圆曲线原理&#xff1a;椭圆曲线的图像并不是椭圆形&#xff0c;椭圆曲线源自于求椭圆弧长的椭圆积分的反函数。定义&#xff1a;椭圆曲线可用下列方程来表示&#xff0c;其中a,b,c,d为系数。E&#xff1a; y2 ax3 bx2 cx d椭圆曲线运算&#xff1a;(相当于交换群)AB&#x…

C 常用新特性(上)

下面是正文&#xff1a;auto类型推导auto可以让编译器在编译器就推导出变量的类型&#xff0c;看代码&#xff1a;利用auto可以通过右边的类型推导出变量的类型。什么时候使用auto呢&#xff1f;简单类型其实没必要使用auto&#xff0c;然而某些复杂类型就有必要使用auto&#…

等级保护测评工作重点难点_重点保护

等级保护测评工作重点难点在“ Java的一些句子 ”一文中&#xff0c;我写道&#xff1a; “受保护的方法和字段可以在同一包中的类中使用&#xff08;到目前为止与私有包相同&#xff09;&#xff0c;此外&#xff0c;还可以从其他类中使用受保护的方法和字段&#xff0c;这些类…

c编译程序是什么?

c编译程序是由计算机厂家提供的一套软件。c编译程序又称c语言编译器&#xff0c;是指用c语言书写的源程序&#xff0c;翻译成等价的机器语言格式目标程序的翻译程序。编译程序属于采用生成性实现途径实现的翻译程序。它以高级程序设计语言书写的源程序作为输入&#xff0c;而以…

运动基元_基元需要走吗?

运动基元我目前正在使用JSF作为视图技术&#xff0c;使用JPA作为持久层的企业应用程序。 它可能是支持bean或服务方法中的某种东西&#xff0c;但令我震惊&#xff1a;是否有充分的理由在企业应用程序中使用原语&#xff1f; 当我开始围绕J2SE 1.2&#xff08;或者是J2SE 5.0&…

mysql 三种工作模式_mybatis三种批量插入方式对比【面试+工作】

准备&#xff1a;1.表结构CREATE TABLE t_user (id varchar(32) CHARACTER SET utf8 NOT NULL COMMENT 主键,name varchar(50) CHARACTER SET utf8 DEFAULT NULL COMMENT 用户名,del_flag char(1) CHARACTER SET utf8 DEFAULT NULL COMMENT 删除标示,PRIMARY KEY (id)) ENGINEI…

C 常用新特性(下)

多线程什么是多线程这里就不过多介绍&#xff0c;新特性关于多线程最主要的就是std::thread的使用&#xff0c;它的使用也很简单&#xff0c;看代码&#xff1a;这里记住&#xff0c;std::thread在其对象生命周期结束时必须要调用join()或者detach()&#xff0c;否则程序会term…

ant 路径_在Ant中显示路径

ant 路径在博客文章Java and Ant Properties Refresher和Ant <echoproperties /> Task中 &#xff0c;我写了一篇关于如何了解Ant构建如何看到属性的文章&#xff0c;这有助于更好地理解该构建。 通常情况下&#xff0c;在构建过程中看到构建中使用的各种路径也很有价值&…

java8默认垃圾回收器,Java 8的默认垃圾收集器

What is the default garbage collector for Java 8?When I check the JMX Beans, they reveal it to be the parallel collector for the new generation and the old serial collector for the old generation.解决方案Selecting the default garbage collector (among othe…

c语言中结束本次循环的语句是什么

c语言中结束本次循环的语句是“continue”。控制语句continue只能作用于循环体中&#xff0c;其作用是结束本次循环&#xff0c;跳到判断循环的位置&#xff0c;即重新开始下一次循环。在C语言中&#xff0c;控制语句“continue”用于循环体中结束本次循环&#xff0c;重新开始…

jdk8 字符串_在JDK 8中连接字符串

jdk8 字符串JDK 8引入了语言功能&#xff0c;例如lambda表达式 &#xff0c; 流 &#xff0c;甚至是新的Date / Time API &#xff0c;这些都会改变我们编写Java应用程序的方式。 但是&#xff0c;还有一些新的API和功能可能不太“改变游戏规则”&#xff0c;但仍为Java编程语言…

C语言中要改变循环语句的流程可以使用的语句有哪些

C语言中要改变循环语句的流程可以使用的语句有&#xff1a;break&#xff0c;continue和goto。break语句可以终止循环而执行整个循环语句后面的代码&#xff1b;continue语句可以跳过循环体中剩余的语句而强制进入下一次循环。break关键字当 break 关键字用于 while、for 循环时…

apk图标存放位置_安卓系统下安装完apk程序后,具体的文件夹位置在哪里呢?

展开全部 有的程序的文件夹是自动建立在sd卡上的,有的程序是没有文件夹的,程序位于32313133353236313431303231363533e59b9ee7ad9431333365666238date/app文件夹内,而系统的程序位于system/app文件夹内。 软件安装完成后,就会在date/app目录出现一个apk文件。 这个文件相当…

java 线程什么时候出栈_在Java中给出的时间

java 线程什么时候出栈tl; dr&#xff0c;您可以使用标签来阐明给定的测试时间样式。 什么时候给出&#xff1f; 给定的时间&#xff0c;然后是指定系统行为的一种常用样式&#xff0c;其中您的测试分为三个部分。 给定的部分列出了测试的先决条件&#xff0c;即在您开始之前…

java 2_Java(二)

二维数组是由一维数组组成的数组选择排序原理将数组中每一个元素与第一个元素相比较&#xff0c;如果这个元素小于第一个元素&#xff0c;则交换这两个元素循环第一条规则&#xff0c;找出最小元素&#xff0c;放于第一个位置经过n-1轮比较完成排序冒泡排序原理逐一比较数组中相…

continue语句只用于循环语句中,它的作用是什么?

continue语句只用于循环语句中&#xff0c;它的作用是&#xff1a;跳过循环体中剩余的语句而强制进入下一次循环。continue语句只用在while、for循环中&#xff0c;常与if条件语句一起使用&#xff0c;判断条件是否成立。continue语句只用在while、for循环中&#xff0c;它的作…

成为java高手_我如何想成为Java

成为java高手我喜欢Java。 我喜欢用Java编程。 但是在使用Python一段时间后&#xff0c;我希望对其进行一些更改。 它几乎纯粹是语法上的&#xff0c;因此可能有更好的JVM语言&#xff0c;但是我并不真正感兴趣&#xff0c;因为我仍然需要使用普通的Java来工作。 我意识到这些更…

在c语言中引用数组元素时,其数组下标的数据类型允许是什么

在c语言中引用数组元素时&#xff0c;其数组下标的数据类型允许是&#xff1a;整型常量或整型表达式。C语言规定只能逐个引用数组元素而不能一次引用整个数组&#xff0c;数据元素的表示形式为“数组名[下标]”&#xff0c;下标可以是整型常量或整型表达式。数组中只有一维数组…

在c语言中char型数据在内存中的储存形式为什么

在c语言中char型数据在内存中的储存形式为“ASCII码”。在C语言中&#xff0c;将一个字符常量放到一个字符变量中&#xff0c;实际并不是把该字符本身放到内存单元中&#xff0c;而是将与该字符相对应的ASCII码放到存储单元中。c语言 char型字符型数据类型就是字符1、字符数据的…