当前位置: 首页 > 编程日记 > 正文

Java中的简单工厂模式(转)

Java中的简单工厂模式

举两个例子以快速明白Java中的简单工厂模式:

女娲抟土造人
话说:“天地开辟,未有人民,女娲抟土为人。”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面。
女娲造人,这就是简单工厂模式的应用。 

  首先,在这个造人的思想里面,有几个重要的角色:女娲本身、抽象的人的概念和女娲所造出的一个个具体的人。
  1.)女娲是一个工厂类,也就是简单工厂模式的核心角色。

2.)具休的一个个的人,包括张三,李四等。这些人便是简单工厂模式里面的具体产品角色
  3.)抽象的人是最早只存在于女娲的头脑里的一个想法,女娲按照这个想法造出的一个个具体的人,便都符合这个抽象的人的定义。换言之,这个抽象的想法规定了所有具体的人必须都有的接口(特征或者功能)
   其UML类图出下所示:
    
理解了上面的这些东西,再来理解下面的例子,对照理解,相信看完这篇文章,便对java简单工厂模式有一个很好的理解:


有一个农场公司,专门向市场销售各类水果,在这个系统里需要描述下列水果:
     葡萄 Grape
     草莓 Stuawberry
     苹果 Apple
水果与其他植物不同,最终可以采摘食用,那么一个自然的做法是建立一个各种水果都适用的接口,以便与其他农场里的植物区分开来,

此时,则是为水果类声明了一个接口,表现在代码上:

 public   interface  Fruit {
 2      // 生长 
 3        void  grow();
 4       // 收获 
 5        void  harvest();
 6       // 种植 
 7        void  plant();
 8 
 9  
10 

水果接口规定出所有的水果必须实现的接口,包括任何水果类必须具备的方法plant(),grow(),和harvest();

Apple类是水果类的一种,因此它实现了水果接口所声明的所有方法。另处,由于苹果是多年生植物,因此多出一个treeAge性质,描述苹果的树龄。代码如下所示:
 package  fac;

 public   class  Apple  implements  Fruit { // 通过implements实现接口Fruit 
      private   int  treeAge;
    
     public   void  grow() {
        log( " Apple is growing " );
    } 
    
     public   void  harvest() {
        log( " Apple has been harvested " );
    } 
    
     public   void  plant() {
        log( " Apple ha been planted " );
    } 
    
     public   static   void  log(String msg) {
        System.out.println(msg);
    } 
    
     public   int  getTreeAge() {
         return  treeAge;
    } 
    
     public   void  setTreeAge( int  treeAge) {
         this .treeAge = treeAge;
    } 


同理,葡萄 Grape:
package fac;

public class Grape implements Fruit{
    private boolean seedless;
    public void grow(){
        log("Grape is growing.");
    }
    
    public void harvest(){
        log("Grape has been harvested");
    }
    
    public void plant(){
        log("Grape ha been planted");
    }
    
    public static void log(String msg){
        System.out.println(msg);
    }

    public boolean isSeedless() {
        return seedless;
    }

    public void setSeedless(boolean seedless) {
        this.seedless = seedless;
    }
    

}

草莓 Stuawberry:
package fac;

public class Strawberry implements Fruit{
    public void grow(){
        log("Strawberry is growing");
    }
    
    public void harvest(){
        log("Strawberry has been harvested");
    }
    
    public void plant(){
        log("Strawberry has been planted");
    }
    
    public static void log(String msg){
        System.out.println(msg);
    }
}


农场园丁也是系统的一部分,由一个类来代表,FruitGardener类,代码如下:
package fac;

public class FruitGardener{
    public static Fruit factory(String which)throws Exception{
        if(which.equalsIgnoreCase("apple")){
            return new Apple();
        }else if(which.equalsIgnoreCase("strawberry")){
            return new Strawberry();
        }else if (which.equalsIgnoreCase("grape")){
            return new Grape();
        }else{
            throw new Exception("Bad fruit request");
        }
    }
}
这时有人来果园玩,和园丁说,给我们介绍下你的水果吧。于是园丁:
package fac;

public class People {

    public static void main(String[] args) throws Exception {
        FruitGardener fg=new FruitGardener();
        Fruit ap=fg.factory("Apple");
        ap.grow();
        Fruit gp=fg.factory("Grape");
        gp.plant();
        
        Fruit dd=fg.factory("ddd");//抛出Bad fruit request异常
    }    

}


(注:以上代码在JDK5.0,Myeclise3.2下编译通过)

类比两个例子,园丁就相当于女娲,而水果就相当于具体的人,接口水果类就相当于存在于类女娲思想里的人的抽象概念。

由以上两个例子可得出,简单工厂模式需要由以下角色组成:
      接口
                        接口的实现类(简单工厂模式里面的具体产品角色)
                        工厂

理解了以下两个例子,再来看第三个例子:
注意对比以下三个实例的不同
实例1:

package org.jzkangta.factorydemo01;
//定义接口
interface Car{
    public void run();
    public void stop();
}
//具体实现类
class Benz implements Car{
    public void run(){
        System.out.println("Benz开始启动了。。。。。");
    }
    public void stop(){
        System.out.println("Benz停车了。。。。。");
    }
}
//具体实现类
class Ford implements Car{
    public void run(){
        System.out.println("Ford开始启动了。。。");
    }
    public void stop(){
        System.out.println("Ford停车了。。。。");
    }
}
//工厂
class Factory{
    public static Car getCarInstance(){
        return new Ford();
    }
}
public class FactoryDemo01 {

    public static void main(String[] args) {
        Car c=Factory.getCarInstance();
        c.run();
        c.stop();

    }

}

实例二:
package fac;


//定义接口
interface Car{
    public void run();
    public void stop();
}
//具体实现类
class Benz implements Car{
    public void run(){
        System.out.println("Benz开始启动了。。。。。");
    }
    public void stop(){
        System.out.println("Benz停车了。。。。。");
    }
}

class Ford implements Car{
    public void run(){
        System.out.println("Ford开始启动了。。。");
    }
    public void stop(){
        System.out.println("Ford停车了。。。。");
    }
}
//工厂
class Factory{
    public static Car getCarInstance(String type){
        Car c=null;
        if("Benz".equals(type)){
            c=new Benz();
        }
        if("Ford".equals(type)){
            c=new Ford();
        }
        return c;
    }
}


public class FactoryDemo02 {

    public static void main(String[] args) {
        Car c=Factory.getCarInstance("Benz");
        if(c!=null){
            c.run();
            c.stop();
        }else{
            System.out.println("造不了这种汽车。。。");
        }
        

    }

}


实例三:
interface Car{
    public void run();
    public void stop();
}

class Benz implements Car{
    public void run(){
        System.out.println("Benz开始启动了。。。。。");
    }
    public void stop(){
        System.out.println("Benz停车了。。。。。");
    }
}

class Ford implements Car{
    public void run(){
        System.out.println("Ford开始启动了。。。");
    }
    public void stop(){
        System.out.println("Ford停车了。。。。");
    }
}

class Toyota implements Car{
    public void run(){
        System.out.println("Toyota开始启动了。。。");
    }
    public void stop(){
        System.out.println("Toyota停车了。。。。");
    }
}

class Factory{
    public static Car getCarInstance(String type){
        Car c=null;
        try {
            c=(Car)Class.forName("org.jzkangta.factorydemo03."+type).newInstance();//利用反射得到汽车类型 
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        return c;
    }
}
public class FactoryDemo03 {

    public static void main(String[] args) {
        Car c=Factory.getCarInstance("Toyota");
        if(c!=null){
            c.run();
            c.stop();
        }else{
            System.out.println("造不了这种汽车。。。");
        }
        

    }

}



对比三个实例:
实例一,虽然实现了简单工厂,但每次只能得到一种汽车,如果我们想换一种,就得修改工厂,太不方便,而实例二则改变了这种情况,便得我们可以按照我们的需要更换汽车,但我们所更换的汽车必须是实现类中有的,如果我们想要增加一种汽车的时候,我们还是得更改工厂,通过改进,实例三利用反射机制,得到汽车类型,这样当我们需要增加一种新的汽车时,就无需要再修改工厂,而只需要增加要实现的类即可。也就是说要增加什么样的汽车直接增加这个汽车的类即可,而无需改变工厂。从而达到了工厂分离的效果。

转载于:https://www.cnblogs.com/bingosblog/p/4180161.html

相关文章:

Math.toRadians()与 Math.toDegrees()方法介绍

strictfp 的意思是FP-strict,也就是说精确浮点的意思。在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运 行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。因此如果你想让你的浮点运算更加精确, 而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp.

Linux命令基础6-mkdir命令

mkdir是英文单词make directory的缩写。mkdir就是用来创建路径&#xff0c;一般就是用来创建文件夹的。 语法 mkdir (选项)(参数) 选项 -Z&#xff1a;设置安全上下文&#xff0c;当使用SELinux时有效&#xff1b; -m<目标属性>或--mode<目标属性>建立目录的同时设…

原子性,可见性,有序性详解及DCL单例模式两次校验的目的(拓展懒汉式,饿汉式)

进入以后进行第二次判断,是因为,对于首个拿锁者,它的时段instance肯定为null,那么进入new Singleton()对象创建,而在首个拿锁者的创建对象期间,可能有其他线程同步调用getInstance(),那么它们也会通过if进入到同步块试图拿锁然后阻塞。如果能够保证2,3的顺序那么就不会存在安全问题,但是实际因为JIT和处理器会对代码进行优化重排序,那么可能会2,3的顺序颠倒,那么就有可能会出现一个线程拿到了一个未被初始完成的对象,从而引发安全问题。,那么在这种情况下,会出现多个实例对象。

3ds Max中的V-Ray学习

时长3h 30m 大小解压后&#xff1a;2.73G 包含项目文件 1280X720 MP4 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 3ds Max中的V-Ray简介:官方V-Ray导师 云桥网络 获取课程&#xff1a;3ds Max中的V-Ray学习 Introduction To V-Ray in 3…

7-5 二分法求多项式单根 (20分)

二分法求函数根的原理为&#xff1a;如果连续函数f(x)在区间[a,b]的两个端点取值异号&#xff0c;即f(a)f(b)<0&#xff0c;则它在这个区间内至少存在1个根r&#xff0c;即f( r )0。 二分法的步骤为&#xff1a; 检查区间长度&#xff0c;如果小于给定阈值&#xff0c;则停…

JAVA的instanceOf什么时候用

我个人理解的一个应用场合就是&#xff0c;当你拿到一个对象的引用时&#xff08;例如参数&#xff09;&#xff0c;你可能需要判断这个引用真正指向的类。所以你需要从该类继承树的最底层开始&#xff0c;使用instanceof操作符判断&#xff0c;第一个结果为true的类即为引用真…

解决谷歌浏览器在非https下限制获取多媒体对象(音视频)的解决方式

1、浏览器输入&#xff1a;chrome://flags/ 2、输入你要允许的域名地址或ip端口地址&#xff08;如下图&#xff09;

After Effects CS4 期末考试卷

AECS4考试A卷转载于:https://blog.51cto.com/hnxdd/1593985

数据图表之圆柱图

需求是这样的&#xff0c;需要一个圆柱实现展示内存的占用变化。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><style>.column{position: relative;width: 300px;height:…

虚幻引擎5–环境设计学习教程

时长:1h 12m |视频:. MP4 1280720&#xff0c;30 fps(r) |音频:AAC&#xff0c;48000 Hz&#xff0c;2ch |大小解压后:1.08G 含课程文件 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 在这节课中&#xff0c;你将学习如何在虚幻引擎5中从…

Java学习总结:38(正则表达式)

正则表达式 正则表达式本质上是一种字符串操作语法规则&#xff0c;利用它我们能更加灵活地实现字符串的匹配、拆分、替换等操作。 正则标记 所有的正则表达式支持的类都定义在java.util.regex包里面。这个包里面定义了如下两个主要的类&#xff1a; 1.Pattern类&#xff1a…

PHP Multipart/form-data remote dos Vulnerability

catalog 1. Description 2. Analysis 1. Description PHP is vulnerable to a remote denial of service, caused by repeatedly allocate memory、concatenate string、copy string and free memory when PHP parses header areas of body part of HTTP request with multipar…

HTTP的KeepAlive是开启还是关闭?

转自&#xff1a;http://blog.csdn.net/gaogaoshan/article/details/38580013 1、KeepAlive的概念与优势 HTTP的KeepAlive就是浏览器和服务端之间保持长连接&#xff0c;这个连接是可以复用的。当客户端发送一次请求&#xff0c;收到相应内容后&#xff0c;这个连接会保持一段时…

MyBatis中jdbcType=INTEGER、VARCHAR作用

Mapper.xml中 pid #{pid,jdbcTypeINTEGER} pid #{pid} 都可以用 Mybatis中什么时候应该声明jdbcType&#xff1f; 当Mybatis不能自动识别你传入对象的类型时。 什么情况下&#xff0c;Mybatis不能自动识别我的传入类型&#xff1f; 例如&#xff1a;当你传入空值的时候。&…

我让老师失去了孩子

我永远也忘不了我的初中班主任是被我们班气得流产的。她教我们历史&#xff0c;中考前那段日子&#xff0c;由于学业紧张&#xff0c;学校又没特殊安排&#xff0c;她天天挺着大肚子给我们讲课&#xff0c;只有偶尔请假离开去医院检检查。我们班成绩不好&#xff0c;学习气氛差…

3D场景高级合成技术学习

MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch |语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09;|时长:3h 47m |大小解压后:3.61 GB 含课程文件 创建和渲染三维场景是一项艰巨的任务。但是当你需要在渲染…

Java学习总结:39(反射机制)

反射机制 JAVA中反射是动态获取信息以及动态调用对象方法的一种反射机制。 Java反射就是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff1b;并且能改变它…

perl 编程 - 判断系统进程是否活着的方法

2019独角兽企业重金招聘Python工程师标准>>> 前言&#xff1a;我在使用perl编写CGI程序时遇到的一些问题&#xff0c;解决以后&#xff0c;记录一下我的心得&#xff0c;有心的朋友们会从中得到帮助并养成正确使用的好习惯。 perl编程中判断系统进程是否存活的方法…

2009 Competition Highlights by ICPC Live

2009 Competition Highlights by ICPC Live Links&#xff1a;http://www.youtube.com/watch?vn0oZRcAz6w0 转载于:https://www.cnblogs.com/yewei/archive/2012/09/07/2674862.html

C4D灯光照明技术学习教程

C4D的灯光照明技术 大小解压后&#xff1a;4.8G 学会用Redshift点亮3D场景&#xff0c;像专业人士一样塑造光线 灯光在任何空间都是至关重要的&#xff0c;无论是真实的还是虚拟的。它能够传递某种感觉或情感。平面设计师罗伯托冈萨雷斯观察到如此重要的方面&#xff0c;并将其…

Java学习总结:40(国际化)

国际化 所谓国际化程序指的是同一套程序代码可以在不同的国家使用&#xff0c;可以根据其应用的国家自动在项目中显示出本国的相应文字信息。 使用Locale类定义语言环境 Locale类的常用方法 No.方法类型描述1public Locale(String language,String country)构造设置使用的语…

AFNetWorking 队列请求

我们在开发过程中&#xff0c;经常会遇到有些页面不止一个网络请求&#xff0c;有时候需要两个三个甚至更多&#xff0c;这个时候我们就需要队列请求&#xff0c;下边是GET请求的多个请求放在队列里边&#xff1a; [objc] view plaincopyprint? NSURL *url [NSURL URLWithStr…

Hadoop-虚拟机环境准备

传送门&#xff1a;https://app.yinxiang.com/fx/4fdf4d09-ddc8-4c67-8bf7-cca1c913fce5

WCF实现RESTFul Web Service

共同学习了前面一些概念&#xff0c;终于开始正题了哈。RESTful的Web Service调用直观&#xff0c;返回的内容容易解析。这里先会描述一个简单的场景--Web Service提供一个方法来搜索个人信息&#xff0c;传入人名&#xff0c;返回完整个人信息。下面我们一步步用WCF实现一个RE…

VS QT插件

支持用VS编译qt工程 QT下载页&#xff1a;http://qt-project.org/downloads qt-vs-addin插件: http://download.qt-project.org/official_releases/vsaddin/qt-vs-addin-1.2.2-opensource.exe 转载于:https://www.cnblogs.com/Leo-Forest/p/3507017.html

使用AutoCAD 2021创建真实世界的土木设计项目

由工程组织创建|最后更新日期:2021年9月 时长:7h 24m | 7节| 64节讲座|视频:1280720&#xff0c;44 KHz | 大小解压后3 GB 流派:电子学习|语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 学会快速使用AutoCAD &#xff1b;专业地制作真实世…

Java学习总结:41(文件操作类:File)

Java文件操作类&#xff1a;File 在java.io包中&#xff0c;如果要进行文件自身的操作(例如&#xff1a;创建、删除等)&#xff0c;只能依靠java.io.File类完成。 File类的常用操作方法 No.方法类型描述1public File(String pathname)构造传递完整文件操作路径2public File(F…

关于大型网站技术演进的思考(四)-存储的瓶颈4

如果数据库需要进行水平拆分&#xff0c;这其实是一件很开心的事情&#xff0c;因为它代表公司的业务正在迅猛的增长&#xff0c;对于开发人员而言那就是有不尽的项目可以做&#xff0c;虽然会感觉很忙&#xff0c;但是人过的充实&#xff0c;心里也踏实。 数据库水平拆分简单说…

2022-2028年中国环卫行业产业链深度调研及投资前景预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国环卫行业市场行业相关概述、中国环卫行业市场行业运行环境、分析了中国环卫行业市场行业的…

curl命令具体解释

对于windows用户假设用Cygwin模拟unix环境的话&#xff0c;里面没有带curl命令&#xff0c;要自己装&#xff0c;所以建议用Gow来模拟&#xff0c;它已经自带了curl工具&#xff0c;安装后直接在cmd环境中用curl命令就可&#xff0c;由于路径已经自己主动给你配置好了。 linux …