【前面的话】

每天过的还行,对我来说,只要让自己充实,生活就会是好的。

学习Java工场方法的原因是最近在使用Spring框架做一个系统,其中有一个注入的方法是使用静态工场方法注入,所以学习一下,基础性文章,选择性阅读。

      这篇文章学习的是静态工厂。

【什么是】

一、定义

     工厂:在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。

     工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”

二、举例

工厂模式是根据不同的参数创建对象。例如用工厂创建小汽车。 如果我们想要一辆奥迪,工厂就会为我们生产一辆奥迪;如果我们需要一辆宝马,工厂则会为我们生产一辆宝马。工厂会根据不同的参数,为我们提供不同的物品。而这些创建的过程就是实例化,也就是是说,对对象实例化的过程封装起来,专门建立一个类进行实例化,这就是工厂模式。

【怎么做】

从下面两段关键代码来看,没有使用静态工厂的代码使得Manager类和具体的实现类紧耦合,如果生产的汽车种类繁多的话,Manager会经常变化,使得Manager类会经常修改,而使用了静态工厂的代码,将所有的实例化都封装在一个工厂类中,以后可能不光是Manager这个类可以调用工厂类,增加的别的方法也是可以调用工厂了。

一、没有使用静态工厂的代码:

1. Manager.java

 public class Manager {
public static Car CreatCar(String type){
Car car = null;//Manager与Audi类和BaoMa类还有Suv类耦合,进行了硬编码
if(type.equals("audi")){
car=new AuDi();
}else if(type.equals("baoma")){
car=new BaoMa();
}else if(type.equals("suv")){
car=new Suv();
}
car.Prepare();
car.Install();
car.Color();
return car;
}
}

二、使用静态工厂的代码:

1. Manager.java

 public class Manager {
Car car = null;
public Car CreatCar(String type){//Manager类和具体类解耦合,不需要关心具体的类的实现方法。
car=CarFactory.getCarInstance(type);//静态方法,不需要使用创建工厂CarFactory来创建对象,直接使用CarFactory来调用其方法。
car.Prepare();
car.Install();
car.Color();
return car;
}
}

2. CarFactory.java

 public class CarFactory {
public static Car getCarInstance(String type){//静态方法,这样做的缺点是如果CarFactory被继承,getCar不能被重写。
Car carInstance = null;
if(type.equals("audi")){
carInstance=new AuDi();
}else if(type.equals("baoma")){
carInstance=new BaoMa();
}else if(type.equals("suv")){
carInstance=new Suv();
}
return carInstance;
}
}

【为什么】

为什么要使用静态工厂模式,这样做的好处如下几点:

第一:静态工厂方法可以突破构造函数不能自由命名的限制,对于不同的工厂方法可以采用不同的会意的名字,是程序具有更好的可读性。JAVA平台库的java.text.Format的子类NumberFormat就有getInstance() , getPrecentInstance() , getCurrencyInstatnce()等静态方法,通过不同的名字产生特定的对象。

第二:静态工厂方法是用来产生对象用的,至于产生什么类型的对象没有限制,这就意味这只要返回原返回类型或原返回类型的子类型都可以,这样就加大了程序设计和使用的灵活行,如java.util集合框架就采用了这种优势,这样就可以更好达到封装的目的,降低API的数目和用户的使用难度,java.util.Connections是集合框架的辅助类用于对原有的集合类进行进一步封装,产生一些同步的集合,不可修改的视图。都是采用静态工厂方法实现的,至于方法内部的实现类就完全别封装了。也迫使我们使用接口编程。

第三:静态工厂方法所创建的对象可以在编译时不存在,动态创建对象,采用放射,类似SPRING的IOC容器方转。最典型的例子就是spi服务提供者框架,Service Provider Iframe 是一种用于在运行时刻产生对象的框架,达到对象的创建与使用分离,是对象的客户和对象之间解耦,增加程序的灵活性和可扩展性。既然spi可以动态创建对象,那么采用什么机制来创建什么对象,创建对象的依据是什么了,spi必须一种统一的注册机制,对于要创建的对象,应该在XML文件中配置,到时候,只要提供一个字符串,就可以凭借该字符串来创建配置的对象

【缺点】

  1. 静态方法,这样做的缺点是如果CarFactory被继承,getCar不能被重写。
  2. 因为我们一般都采用的是构造函数进行实例化对象,而采用静态工厂的方法进行实例化就会使得实例化和构造函数实例化不一样,所以增加了使用难度,一般都要采用较为清晰的命名,使得使用者可以一目了然知道使用了静态方法。
  3. 如果例子中某一个具体类的构造函数式私有,就会出现错误。

【代码举例】

下面记录了两个代码demo,一个是没有使用静态工厂方法的demo,一个是使用了静态工厂方法的demo。

一、不是用静态工厂模式的代码

1. AuDi.java

 public class AuDi implements Car {
public void Prepare(){
System.out.println("我是奥迪车,我在进行生产准备");
}
public void Install(){
System.out.println("我是奥迪车,我在进行组装");
}
public void Color(){
System.out.println("我是奥迪车,我在进行着色");
}
}

2. BaoMa.java

 public class BaoMa implements Car{
public void Prepare(){
System.out.println("我是宝马车,我在进行生产准备");
}
public void Install(){
System.out.println("我是宝马车,我在进行组装");
}
public void Color(){
System.out.println("我是宝马车,我在进行着色");
}
}

3. Suv.java

 public class Suv implements Car{
public void Prepare(){
System.out.println("我是SUV车,我在进行生产准备");
}
public void Install(){
System.out.println("我是SUV车,我在进行组装");
}
public void Color(){
System.out.println("我是SUV车,我在进行着色");
}
}

4. Car.java

 public interface Car {
public abstract void Prepare();
public abstract void Install();
public abstract void Color();
}

5. Manager.java

 public class Manager {
public static Car CreatCar(String type){
Car car = null;//Manager与Audi类和BaoMa类还有Suv类耦合,进行了硬编码
if(type.equals("audi")){
car=new AuDi();
}else if(type.equals("baoma")){
car=new BaoMa();
}else if(type.equals("suv")){
car=new Suv();
}
car.Prepare();
car.Install();
car.Color();
return car;
}
}

6. MainTest.java

 public class MainTest {
public static void main(String[] args){
Manager.CreatCar("audi");
Manager.CreatCar("baoma");
Manager.CreatCar("suv");
}
}

7. 运行结果:

 我是奥迪车,我在进行生产准备
我是奥迪车,我在进行组装
我是奥迪车,我在进行着色
我是宝马车,我在进行生产准备
我是宝马车,我在进行组装
我是宝马车,我在进行着色
我是SUV车,我在进行生产准备
我是SUV车,我在进行组装
我是SUV车,我在进行着色

二、使用静态工厂模式的代码

1. AuDi.java

 public class AuDi implements Car {
public void Prepare(){
System.out.println("我是奥迪车,我在进行生产准备");
}
public void Install(){
System.out.println("我是奥迪车,我在进行组装");
}
public void Color(){
System.out.println("我是奥迪车,我在进行着色");
}
}

2. BaoMa.java

 public class BaoMa implements Car{
public void Prepare(){
System.out.println("我是宝马车,我在进行生产准备");
}
public void Install(){
System.out.println("我是宝马车,我在进行组装");
}
public void Color(){
System.out.println("我是宝马车,我在进行着色");
}
}

3. Suv.java

 public class Suv implements Car{
public void Prepare(){
System.out.println("我是SUV车,我在进行生产准备");
}
public void Install(){
System.out.println("我是SUV车,我在进行组装");
}
public void Color(){
System.out.println("我是SUV车,我在进行着色");
}
}

4. Car.java

 public interface Car {
public abstract void Prepare();
public abstract void Install();
public abstract void Color();
}

5. Manager.java

 public class Manager {
Car car = null;
public Car CreatCar(String type){//Manager类和具体类解耦合,不需要关心具体的类的实现方法。
car=CarFactory.getCarInstance(type);//静态方法,不需要使用创建工厂CarFactory来创建对象,直接使用CarFactory来调用其方法。
car.Prepare();
car.Install();
car.Color();
return car;
}
}

6.CarFactory.java

 public class CarFactory {
public static Car getCarInstance(String type){//静态方法,这样做的缺点是如果CarFactory被继承,getCar不能被重写。
Car carInstance = null;
if(type.equals("audi")){
carInstance=new AuDi();
}else if(type.equals("baoma")){
carInstance=new BaoMa();
}else if(type.equals("suv")){
carInstance=new Suv();
}
return carInstance;
}
}

7.MainTest.java

 public class MainTest {
public static void main(String[] args){
Manager manager=new Manager();
manager.CreatCar("audi");
manager.CreatCar("baoma");
manager.CreatCar("suv");
}
}

8.运行结果:

 我是奥迪车,我在进行生产准备
我是奥迪车,我在进行组装
我是奥迪车,我在进行着色
我是宝马车,我在进行生产准备
我是宝马车,我在进行组装
我是宝马车,我在进行着色
我是SUV车,我在进行生产准备
我是SUV车,我在进行组装
我是SUV车,我在进行着色

【资料下载】

代码demo下载:http://download.csdn.net/detail/xtbda/7096469

【参考资料】

  1. 讲故事,学(Java)设计模式—工厂模式  http://www.importnew.com/6718.html
  2. 工厂方法设计模式的最佳实践 http://www.importnew.com/10286.html
  3. 静态工厂方法http://blog.csdn.net/mingyunduoshou/article/details/6149758
  4. 《Head First设计模式》Eric Freeman&Elisabeth Freeman著

【后面的话】

好好学习,最近学习稍微显得有点乱,要有步骤,有计划。

——TT

Java学习笔记(十四)——Java静态工厂的更多相关文章

  1. Java学习笔记十四:如何定义Java中的类以及使用对象的属性

    如何定义Java中的类以及使用对象的属性 一:类的重要性: 所有Java程序都以类class为组织单元: 二:什么是类: 类是模子,确定对象将会拥有的特征(属性)和行为(方法): 三:类的组成: 属性 ...

  2. Java学习笔记十八:Java面向对象的三大特性之封装

    Java面向对象的三大特性之封装 一:面向对象的三大特性: 封装 继承 多态   二:封装的概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访 ...

  3. Java学习笔记十五:Java中的成员变量和局部变量

    Java中的成员变量和局部变量 一:成员变量: 成员变量在类中定义,用来描述对象将要有什么 成员变量可以被本类的方法使用,也可以被其他类的方法使用,成员变量的作用域在整个类内部都是可见的 二:局部变量 ...

  4. Java 读书笔记 (十四) Java 方法

    finalize() 方法 finalize() 用来清除回收对象.  //为什么要回收内存?怎样写可以避免内存过多占用?什么时候需要手动回收内存? protected void finalize() ...

  5. Java学习笔记十九:Java中的访问控制修饰符

    Java中的访问控制修饰符 一:Java修饰符的种类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class Hello ...

  6. Java学习笔记十六:Java中的构造方法

    Java中的构造方法 1.使用new+构造方法 创建一个新的对象: 2.构造方法是定义在Java类中的一个用来初始化对象的方法: 3.构造方法与类同名且没有返回值: 4.语法格式: public 构造 ...

  7. Java学习笔记十二:Java中方法的重载

    Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ...

  8. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  9. 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类

    static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...

  10. Java学习笔记心得——初识Java

    初识Java 拿到这本厚厚的<Java学习笔记>,翻开目录:Java平台概论.从JDK到TDE.认识对象.封装.继承与多态...看着这些似懂非懂的术语名词,心里怀着些好奇与担忧,就这样我开 ...

随机推荐

  1. JS传递中文参数出现乱码的解决办法

    一.window.open() 乱码: JS中使用window.open("url?param="+paramvalue)传递参数出现乱码,提交的时候,客户端浏览器URL中显示参数 ...

  2. STL之三:deque用法详解

    转载于:http://blog.csdn.net/longshengguoji/article/details/8519812 deque函数: deque容器为一个给定类型的元素进行线性处理,像向量 ...

  3. Codeforces Round #340 (Div. 2) D

    D. Polyline time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...

  4. bzoj4810 [Ynoi2017]由乃的玉米田 bitset优化+暴力+莫队

    [Ynoi2017]由乃的玉米田 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 917  Solved: 447[Submit][Status][Di ...

  5. Leetcode 380. 常数时间插入、删除和获取随机元素

    1.题目描述 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构. insert(val):当元素 val 不存在时,向集合中插入该项. remove(val):元素 val 存在时 ...

  6. ListBox, ListView, GridView

    ListView是ListBox的派生类,而GridView是ViewBase的派生类 ListView的View属性是ViewBase,所以GridView可以作为ListView的属性 如 < ...

  7. mysql 压缩包免安装版 安转步骤

    一. 下载 MySQL 的官网下载地址:http://www.mysql.com/downloads/ 在这个下载界面会有几个版本的选择. 1. MySQL Community Server 社区版本 ...

  8. UVA 1638 Pole Arrangement

    https://vjudge.net/problem/UVA-1638 题意: n根长度分别为1,2,3,4……n的木棍 将这些木棍竖着排成一列 问从左边看能看到L根,从右边看能看到R根的方案数 将木 ...

  9. 求逆元的两种方法+求逆元的O(n)递推算法

    到国庆假期都是复习阶段..所以把一些东西整理重温一下. gcd(a,p)=1,ax≡1(%p),则x为a的逆元.注意前提:gcd(a,p)=1; 方法一:拓展欧几里得 gcd(a,p)=1,ax≡1( ...

  10. 静态资源(JS/CSS)存储在localStorage

    一.简单了解SEO SEO由英文Search Engine Optimization缩写而来, 中文意译为“搜索引擎优化”.SEO是指从自然搜索结果获得网站流量的技术和过程. 搜索引擎不优化的网站分为 ...