• Java学习笔记(十四)——Java静态工厂


    【前面的话】

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

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

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

    【什么是】

    一、定义

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

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

    二、举例

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

    【怎么做】

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

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

         1. Manager.java

     1 public class Manager {
     2        public static Car CreatCar(String type){
     3         Car car = null;//Manager与Audi类和BaoMa类还有Suv类耦合,进行了硬编码
     4         if(type.equals("audi")){
     5             car=new AuDi();
     6         }else if(type.equals("baoma")){
     7             car=new BaoMa();
     8         }else if(type.equals("suv")){
     9             car=new Suv();
    10         }
    11         car.Prepare();
    12         car.Install();
    13         car.Color();
    14         return car;
    15     }
    16 }

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

        1. Manager.java

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

        2. CarFactory.java

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

    【为什么】

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

           第一:静态工厂方法可以突破构造函数不能自由命名的限制,对于不同的工厂方法可以采用不同的会意的名字,是程序具有更好的可读性。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

     1 public class AuDi implements Car {
     2     public void Prepare(){
     3         System.out.println("我是奥迪车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是奥迪车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是奥迪车,我在进行着色");
    10     }
    11 }
    View Code

        2. BaoMa.java

     1 public class BaoMa implements Car{
     2     public void Prepare(){
     3         System.out.println("我是宝马车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是宝马车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是宝马车,我在进行着色");
    10     }
    11 }
    View Code

       3. Suv.java

     1 public class Suv implements Car{
     2     public void Prepare(){
     3         System.out.println("我是SUV车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是SUV车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是SUV车,我在进行着色");
    10     }
    11 }
    View Code

       4. Car.java

    1 public interface Car {
    2     public abstract void Prepare();
    3     public abstract void Install();
    4     public abstract void Color();
    5 }
    View Code

        5. Manager.java

     1 public class Manager {
     2        public static Car CreatCar(String type){
     3         Car car = null;//Manager与Audi类和BaoMa类还有Suv类耦合,进行了硬编码
     4         if(type.equals("audi")){
     5             car=new AuDi();
     6         }else if(type.equals("baoma")){
     7             car=new BaoMa();
     8         }else if(type.equals("suv")){
     9             car=new Suv();
    10         }
    11         car.Prepare();
    12         car.Install();
    13         car.Color();
    14         return car;
    15     }
    16 }
    View Code

        6. MainTest.java

    1 public class MainTest {
    2     public static void main(String[] args){
    3         Manager.CreatCar("audi"); 
    4         Manager.CreatCar("baoma"); 
    5         Manager.CreatCar("suv"); 
    6      }
    7 }
    View Code

        7. 运行结果:

    1 我是奥迪车,我在进行生产准备
    2 我是奥迪车,我在进行组装
    3 我是奥迪车,我在进行着色
    4 我是宝马车,我在进行生产准备
    5 我是宝马车,我在进行组装
    6 我是宝马车,我在进行着色
    7 我是SUV车,我在进行生产准备
    8 我是SUV车,我在进行组装
    9 我是SUV车,我在进行着色
    View Code

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

        1. AuDi.java

     1 public class AuDi implements Car {
     2     public void Prepare(){
     3         System.out.println("我是奥迪车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是奥迪车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是奥迪车,我在进行着色");
    10     }
    11 }
    View Code

        2. BaoMa.java

     1 public class BaoMa implements Car{
     2     public void Prepare(){
     3         System.out.println("我是宝马车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是宝马车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是宝马车,我在进行着色");
    10     }
    11 }
    View Code

        3. Suv.java

     1 public class Suv implements Car{
     2     public void Prepare(){
     3         System.out.println("我是SUV车,我在进行生产准备");
     4     }
     5     public void Install(){
     6         System.out.println("我是SUV车,我在进行组装");
     7     }
     8     public void Color(){
     9         System.out.println("我是SUV车,我在进行着色");
    10     }
    11 }
    View Code

        4. Car.java

    1 public interface Car {
    2     public abstract void Prepare();
    3     public abstract void Install();
    4     public abstract void Color();
    5 }
    View Code

        5. Manager.java

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

        6.CarFactory.java

     1 public class CarFactory {
     2     public static Car getCarInstance(String type){//静态方法,这样做的缺点是如果CarFactory被继承,getCar不能被重写。
     3         Car carInstance = null;
     4         if(type.equals("audi")){
     5             carInstance=new AuDi();
     6         }else if(type.equals("baoma")){
     7             carInstance=new BaoMa();
     8         }else if(type.equals("suv")){
     9             carInstance=new Suv();
    10         }
    11         return carInstance;
    12     }
    13 }
    View Code

        7.MainTest.java

    1 public class MainTest {
    2     public static void main(String[] args){
    3         Manager manager=new Manager();
    4         manager.CreatCar("audi"); 
    5         manager.CreatCar("baoma"); 
    6         manager.CreatCar("suv"); 
    7      }
    8 }
    View Code

        8.运行结果:

    1 我是奥迪车,我在进行生产准备
    2 我是奥迪车,我在进行组装
    3 我是奥迪车,我在进行着色
    4 我是宝马车,我在进行生产准备
    5 我是宝马车,我在进行组装
    6 我是宝马车,我在进行着色
    7 我是SUV车,我在进行生产准备
    8 我是SUV车,我在进行组装
    9 我是SUV车,我在进行着色
    View Code

    【资料下载】

     代码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

     

  • 相关阅读:
    网络流练习
    Noip2018 游记
    4719: [Noip2016]天天爱跑步
    1875: [SDOI2009]HH去散步
    P2619 [国家集训队2]Tree I
    1493: [NOI2007]项链工厂
    P1710 地铁涨价
    P3694 邦邦的大合唱站队
    P1439 【模板】最长公共子序列
    P1132 数字生成游戏
  • 原文地址:https://www.cnblogs.com/xt0810/p/3623355.html
Copyright © 2020-2023  润新知