Java创新型模式_java设计模式--创建型模式(一)

2016-04-24 10:10:34

创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式

注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。

而GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory),这是将简单工厂模式(Simple Factory)看成了工厂方法模式的一种特例,两者归为了一类。

工厂方法模式:

(1)简单工厂模式(又叫静态工厂方法模式)

通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式中包含的角色及其职责:

1.工厂(Creator)角色

简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

2.抽象(Product)角色

简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

3.具体产品(Concrete Product)角色

简单工厂模式所创建的具体实例对象

例子:采集水果,如苹果、香蕉

Apple和Banana是具体产品角色;Fruit是抽象角色,是Apple和Banana的公共接口;FruitFactory是工厂角色,负责创建Apple和Banana实例。

public interfaceFruit {/** 采集*/

public voidget();

}

public class Apple implementsFruit{/** 采集*/

public voidget(){

System.out.println("采集苹果");

}

}

public class Banana implementsFruit{/** 采集*/

public voidget(){

System.out.println("采集香蕉");

}

public classFruitFactory {/** 获得Apple类的实例*/

public staticFruit getApple() {return newApple();

}/** 获得Banana类实例*/

public staticFruit getBanana() {return newBanana();

}

}

public classMainClass {public static voidmain(String[] args) {

Fruit apple=FruitFactory.getApple();

Fruit banana=FruitFactory.getBanana();

apple.get();

banana.get();

}

还可以如下修改FruitFactory类

public classFruitFactory {/** getFruit方法,获得所有产品对象*/

public static Fruit getFruit(String type) throwsInstantiationException, IllegalAccessException, ClassNotFoundException {

Class fruit=Class.forName(type);return(Fruit) fruit.newInstance();

}

}

这样动态的加载和创建Class类,但是没有注意大小写;

进一步修改为:

public classFruitFactory {/** getFruit方法,获得所有产品对象*/

public static Fruit getFruit(String type) throwsInstantiationException, IllegalAccessException, ClassNotFoundException {if(type.equalsIgnoreCase("apple")) {return Apple.class.newInstance();

}else if(type.equalsIgnoreCase("banana")) {return Banana.class.newInstance();

}else{

System.out.println("找不到相应的实例化类");return null;

}

}

}

然后

public classMainClass {public static void main(String[] args) throwsInstantiationException, IllegalAccessException, ClassNotFoundException {

Fruit apple= FruitFactory.getFruit("Apple");

Fruit banana= FruitFactory.getFruit("Banana");

apple.get();

banana.get();

}

}

简单工厂模式的优缺点:

在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。

不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。例如增加一种水果-梨子,需要在FruitFactory中继续增加else if语句,不符合开放封闭原则。这时候考虑下面的工厂方法模式。

(2)工厂方法模式(又叫多态工厂模式)

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

模式中包含的角色及其职责:

1.抽象工厂(Creator)角色

工厂方法模式的核心,任何工厂类都必须实现这个接口。

2.具体工厂( Concrete

Creator)角色

具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

3.抽象(Product)角色

工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

4.具体产品(Concrete Product)角色

工厂方法模式所创建的具体实例对象

例子:采集水果,如苹果、香蕉、梨子

Apple、Banana、Pear是具体产品角色;Fruit是抽象角色,是Apple、Banana、Pear的公共接口。他们的构造和前面简单工厂模式中一样。

AppleFactory、BananaFactory、PearFactory是具体工厂角色,负责创建Apple、Banana、Pear的实例;FruitFactory是抽象工厂角色,是AppleFactory、BananaFactory、PearFactory的公共接口。

public interfaceFruitFactory {//水果厂

publicFruit getFruit();

}

public class AppleFactory implementsFruitFactory {//苹果厂,返回苹果实例

publicFruit getFruit() {return newApple();

}

}

public class BananaFactory implementsFruitFactory {//香蕉厂,返回香蕉实例

publicFruit getFruit() {return newBanana();

}

}

public class PearFactory implementsFruitFactory {//梨子厂,返回梨子实例

publicFruit getFruit() {return newPear();

}

}

public classMainClass {public static voidmain(String[] args) {//获得AppleFactory

FruitFactory ff = newAppleFactory();//通过AppleFactory来获得Apple实例对象

Fruit apple =ff.getApple();

apple.get();//获得BananaFactory

FruitFactory ff2 = newBananaFactory();//通过BananaFactory来获得Banana实例对象

Fruit banana =ff2.getBanana();

banana.get();//获得PearFactory

FruitFactory ff3 = newPearFactory();//通过PearFactory来获得Pear实例对象

Fruit pear =ff3.getPear();

pear.get();

}

}

和简单工厂模式比较:工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

affa19ecc1d2fe19da74219ffd7a2c07.png

Apple、Pear属于产品等级结构;Apple又分南方Apple和北方Apple;Pear也分南方Pear和北方Pear。

一个工厂负责生产南方的Apple、Pear,这是一个产品族;一个工厂负责生产北方的Apple、Pear,这是另一个产品族。

模式中包含的角色及其职责:

1.抽象工厂(Creator)角色

抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

2.具体工厂( Concrete  Creator)角色

具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。

3.抽象(Product)角色

抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

4.具体产品(Concrete Product)角色

抽象模式所创建的具体实例对象

注意:抽象工厂中方法对应产品结构,具体工厂对应产品族。

FruitFactory是抽象工厂角色,里面声明了苹果和梨子;SouthFactory和NorthFactory是具体工厂角色,SouthFactory返回南方苹果和梨子实例,NorthFactory返回北方苹果和梨子实例。

public interfaceFruit {/** 采集*/

public voidget();

}

public abstract class Apple implementsFruit{/** 采集苹果*/

public abstract voidget();

}

public abstract class Pear implementsFruit{/** 采集梨子*/

public abstract voidget();

}

public class SouthApple extendsApple {public voidget() {

System.out.println("采集南方苹果");

}

}

public class NorthApple extendsApple {public voidget() {

System.out.println("采集北方苹果");

}

}

public class SouthPear extendsPear {public voidget() {

System.out.println("采集南方梨子");

}

}

public class NorthPear extendsPear {public voidget() {

System.out.println("采集北方梨子");

}

}

public interfaceFruitFactory {//实例化Apple

publicFruit getApple();//实例化Pear

publicFruit getPear();

}

public class SouthFruitFactory implementsFruitFactory {publicFruit getApple() {return newSouthApple();

}publicFruit getPear() {return newSouthPear();

}

}

public class NorthFruitFactory implementsFruitFactory {publicFruit getApple() {return newNorthApple();

}publicFruit getPear() {return newNorthPear();

}

}

public classMainClass {public static voidmain(String[] args) {

FruitFactory ff= newNorthFruitFactory();

Fruit apple=ff.getApple();

apple.get();

Fruit banana=ff.getPear();

pear.get();

FruitFactory ff2= newSouthFruitFactory();

Fruit apple2=ff2.getApple();

apple2.get();

Fruit banana2=ff2.getPear();

pear2.get();

}

}

如果再增加一个产品族:温室水果,包括温室苹果和温室梨子,只要增加相应的温室苹果类、温室梨子类和温室工厂类,符合“开放-封闭“”原则。但是若增加的是一个产品,如香蕉,则会违反该原则。

补充:工厂模式在开发中的应用

一个简单的计算器(主要是加法运算):

OperationFactory是抽象工厂类,AddOperationFactory是具体工厂类;Operation是抽象角色类;AddOperation和SubtractionOperation是具体角色类。

public abstract classOperation {private doublenum1;private doublenum2;public doublegetNum1() {returnnum1;

}public void setNum1(doublenum1) {this.num1 =num1;

}public doublegetNum2() {returnnum2;

}public void setNum2(doublenum2) {this.num2 =num2;

}public abstract doublegetResult();

}

public class AddOperation extendsOperation {public doublegetResult() {double result = this.getNum1() + this.getNum2();returnresult;

}

}

public class SubtractionOperation extendsOperation {public doublegetResult() {double result = this.getNum1() - this.getNum2();returnresult;

}

}

public interfaceOperationFactory {publicOperation getOperation();

}

public class AddOperationFactory implementsOperationFactory{publicOperation getOperation() {return newAddOperation();

}

}

importjava.util.Scanner;public classMainClass {public static voidmain(String[] args) {//1.接受控制台输入

System.out.println("---计算器程序---");

System.out.println("输入第一个操作数");

Scanner scanner= newScanner(System.in);

String strNum1=scanner.nextLine();

System.out.println("输入运算符");

String oper=scanner.nextLine();

System.out.println("输入第二个操作数");

String strNum2=scanner.nextLine();double result = 0;double num1 =Double.parseDouble(strNum1);double num2 =Double.parseDouble(strNum2);//2.进行运算

if("+".equals(oper)) {

OperationFactory factory= newAddOperationFactory();

Operation operation=factory.getOperation();

operation.setNum1(num1);

operation.setNum2(num2);

result=operation.getResult();

}//3.返回结果

System.out.println(strNum1 + oper + strNum2 + "=" +result);

}

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

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

相关文章

原来这就是C语言的基本结构—循环结构?!

点击上方蓝字关注我,了解更多咨询今天我们就着重说说循环结构。循环结构分为三种,分别是for、while、dowhile;我们首先说第一种:for循环..他的代码格式为:for(判断的数值初始化;判断条件;改变判断数值大小){循环语句块&#xff1b…

java count 在哪一类里_java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用...

先来讲解一下Semaphore信号灯的作用:可以维护当前访问自身的线程个数,并提供了同步机制,使用semaphore可以控制同时访问资源的线程个数例如,实现一个文件允许的并发访问数。请看下面的演示代码:1 public classSemaphoreTest2 {3 public stati…

C/C++入门易错点及常用小技巧

点击上方蓝字关注我,了解更多咨询C语言诞生至今已有30多个年头了,主要集中在需要运行效率比较高的行业,比如现在的游戏开发以及高效服务器等等。C学习难度比其它语言都要高,这是不可否认的,其学习难度主要在于它的复杂…

quasar_Quasar和Akka –比较

quasaractor模型是用于容错和高度可扩展系统的设计模式。 角色是独立的工作程序模块,它们仅通过消息传递与其他角色进行通信,可以与其他角色隔离而失败,但是可以监视其他角色的故障并在发生这种情况时采取一些恢复措施。 角色是简单&#xff…

什么是自定义函数?精简回答

点击上方蓝字关注我,了解更多咨询1、自定义函数是程序员根据所要完成的功能,自己写出的源代码实现该功能。2、自定义函数和库函数一样,具有函数名,返回值类型,和函数参数。示例1:写一个函数找出两整数的值。…

C++ 创建文件夹的几种方式汇总确定不来看看???

点击上方蓝字关注我,了解更多咨询1、使用 system() 调用 dos 命令。2、使用头文件 direct.h 中的 access 和 mkdir 函数。关于 direct.h 我觉得 维基百科 上介绍的不错3、调用 Windows API 函数。4、调用 MFC 封装好的接口函数。不推荐此方法,出错的话会…

java socket 传送进度_java-★-Socket文件上传/进度条

客户端代码:1、客户端运行程序:package wtb.khd;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.OutputStream;import …

c语言中typedef和define的区别

点击上方蓝字关注我&#xff0c;了解更多咨询1、typedef仅限于为类型定义符号名称。define不仅可以为类型定义别名&#xff0c;还可以为数值定义别名。例如&#xff0c;可以将1定义为ONE。2、typedef由编译器解释&#xff0c;define语句由预编译器处理。实例#include <stdio…

c语言中预处理器是什么?

点击上方蓝字关注我&#xff0c;了解更多咨询1、C语言有预处理器&#xff0c;Java中没有这个概念&#xff0c;其实只是文本替换工具。2、C的预处理器&#xff0c;即CPP&#xff0c;将在实际编译器中完成处理&#xff0c;所有预处理命令将从#开始。实例#include <stdio.h>…

垃圾回收算法以及垃圾回收器_什么是垃圾回收?

垃圾回收算法以及垃圾回收器以下是我们的垃圾收集手册中的一个示例&#xff0c;该手册将在接下来的几周内发布。 同时&#xff0c;花点时间熟悉垃圾收集的基础知识-这将是本书的第一章。 乍一看&#xff0c;垃圾收集应该处理顾名思义的问题–查找并丢弃垃圾。 实际上&#xff…

c语言中fgetc函数的介绍

点击上方蓝字关注我&#xff0c;了解更多咨询1、fgetc函数返回的字符实际上是文件流中位置指针指向的字符。当fgetc函数读取错误时&#xff0c;返回EOF并设置文件错误标志位。2、该函数以无符号char强制转换为int的形式返回读取的字符&#xff0c;如果到达文件末尾或出现读错&a…

花5分钟了解C语言基本语法元素快来

点击上方蓝字关注我&#xff0c;了解更多咨询C语言是一种编程语言&#xff0c;和其它语言一样&#xff0c;也定义了自己的语法和词汇。学习C语言&#xff0c;首先要学习C语言的词汇&#xff0c;再学习C语言的语法规则&#xff0c;然后由词汇构成语句&#xff0c;由语句构成源程…

c语言中ftell函数是什么

点击上方蓝字关注我&#xff0c;了解更多咨询1、C语言函数ftell用于获取文件位置指针当前位置相对于文件首的偏移字节数。2、通过ftell函数获取当前文件的大小&#xff0c;然后通过fread函数读取缓冲区。返回值&#xff0c;如果成功&#xff0c;该函数返回位置标识符的当前值&a…

jdk入门_JDK 9 REPL:入门

jdk入门会议是聚会Java名人的好地方。 Devoxx France是与Java语言架构师&#xff0c;前同事和老朋友Brian Goetz&#xff08; briangoetz &#xff09;见面的一个机会。 我们谈论了JDK 9&#xff0c;而他全都热衷于REPL。 他提到&#xff0c;尽管Java SE 9中有很多重要功能 &am…

c语言中局部变量是什么

点击上方蓝字关注我&#xff0c;了解更多咨询1、函数内部定义的变量称为局部变量&#xff0c;其作用域仅限于函数内部&#xff0c;离开函数后无效&#xff0c;使用后报错。2、局部变量只能在函数内部使用&#xff0c;离开函数后无效&#xff0c;再次使用会报错。实例#include &…

java接口自动化Excel占位符_基于maven+java+TestNG+httpclient+poi+jsonpath+ExtentReport的接口自动化测试框架...

接口自动化框架项目说明本框架是一套基于mavenjavaTestNGhttpclientpoijsonpathExtentReport而设计的数据驱动接口自动化测试框架&#xff0c;TestNG 作为执行器&#xff0c;poi用于读取存放于excel的接口用例&#xff0c;jsonPath用于校验返回值&#xff0c;以及提取返回值。本…

C语言为什么要定义short,int,long这么多整数类型?

点击上方蓝字关注我&#xff0c;了解更多咨询整数类型有int、short int、long int三种类型&#xff0c;用于需要不同存储空间的整数使用。整数类型有正整数和负整数之分&#xff0c;在C语言中&#xff0c;规定整型的最高位为符号位&#xff0c;最高位为“0”表示正数&#xff0…

c语言中函数参数类型的探究

点击上方蓝字关注我&#xff0c;了解更多咨询函数中的参数个数可以是0&#xff0c;也可以是一个或多个参数。下面我们带着这三种不同的情况&#xff0c;分别在c语言中进行讨论。1、函数没有参数&#xff0c;表示没有参数列表。int func1(); //声明一个函数&#xff0c;该函数…

c语言野指针产生的原因

点击上方蓝字关注我&#xff0c;了解更多咨询1、指针变量未初始化&#xff0c;任何指针变量刚被创建时不会自动成为 NULL 指针&#xff0c;它的缺省值是随机的。所以&#xff0c;指针变量在创建的同时应当被初始化&#xff0c;要么将指针设置为 NULL &#xff0c;要么让它指向合…

c语言中assert函数的使用注意

点击上方蓝字关注我&#xff0c;了解更多咨询1、使用assert检查函数开始时传入参数的合法性。2、每个assert只检验一个条件&#xff0c;因为在同时检验多个条件时&#xff0c;如果断言失败&#xff0c;就无法直观地判断哪个条件失败。实例int resetBufferSize(int nNewSize) {/…