Java学习笔记(十四)——Java静态工厂
【前面的话】
每天过的还行,对我来说,只要让自己充实,生活就会是好的。
学习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文件中配置,到时候,只要提供一个字符串,就可以凭借该字符串来创建配置的对象
【缺点】
- 静态方法,这样做的缺点是如果CarFactory被继承,getCar不能被重写。
- 因为我们一般都采用的是构造函数进行实例化对象,而采用静态工厂的方法进行实例化就会使得实例化和构造函数实例化不一样,所以增加了使用难度,一般都要采用较为清晰的命名,使得使用者可以一目了然知道使用了静态方法。
- 如果例子中某一个具体类的构造函数式私有,就会出现错误。
【代码举例】
下面记录了两个代码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
【参考资料】
- 讲故事,学(Java)设计模式—工厂模式 http://www.importnew.com/6718.html
- 工厂方法设计模式的最佳实践 http://www.importnew.com/10286.html
- 静态工厂方法http://blog.csdn.net/mingyunduoshou/article/details/6149758
- 《Head First设计模式》Eric Freeman&Elisabeth Freeman著
【后面的话】
好好学习,最近学习稍微显得有点乱,要有步骤,有计划。
——TT
Java学习笔记(十四)——Java静态工厂的更多相关文章
- Java学习笔记十四:如何定义Java中的类以及使用对象的属性
		如何定义Java中的类以及使用对象的属性 一:类的重要性: 所有Java程序都以类class为组织单元: 二:什么是类: 类是模子,确定对象将会拥有的特征(属性)和行为(方法): 三:类的组成: 属性 ... 
- Java学习笔记十八:Java面向对象的三大特性之封装
		Java面向对象的三大特性之封装 一:面向对象的三大特性: 封装 继承 多态 二:封装的概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访 ... 
- Java学习笔记十五:Java中的成员变量和局部变量
		Java中的成员变量和局部变量 一:成员变量: 成员变量在类中定义,用来描述对象将要有什么 成员变量可以被本类的方法使用,也可以被其他类的方法使用,成员变量的作用域在整个类内部都是可见的 二:局部变量 ... 
- Java 读书笔记 (十四) Java 方法
		finalize() 方法 finalize() 用来清除回收对象. //为什么要回收内存?怎样写可以避免内存过多占用?什么时候需要手动回收内存? protected void finalize() ... 
- Java学习笔记十九:Java中的访问控制修饰符
		Java中的访问控制修饰符 一:Java修饰符的种类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class Hello ... 
- Java学习笔记十六:Java中的构造方法
		Java中的构造方法 1.使用new+构造方法 创建一个新的对象: 2.构造方法是定义在Java类中的一个用来初始化对象的方法: 3.构造方法与类同名且没有返回值: 4.语法格式: public 构造 ... 
- Java学习笔记十二:Java中方法的重载
		Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ... 
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
		python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ... 
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
		static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ... 
- Java学习笔记心得——初识Java
		初识Java 拿到这本厚厚的<Java学习笔记>,翻开目录:Java平台概论.从JDK到TDE.认识对象.封装.继承与多态...看着这些似懂非懂的术语名词,心里怀着些好奇与担忧,就这样我开 ... 
随机推荐
- 如何设置Eclipse使用JDK
			1.打开Eclipse,选择Windows->Preferences,如图所示: 2.配置本地安装的jdk,如图所示: 注意:首先要先安装JDK. 木头大哥所发的文章均基于自身实践, ... 
- Codeforces Round #396 (Div. 2) A B C D 水 trick dp 并查集
			A. Mahmoud and Longest Uncommon Subsequence time limit per test 2 seconds memory limit per test 256 ... 
- Good Bye 2015 C
			C. New Year and Domino time limit per test 3 seconds memory limit per test 256 megabytes input stand ... 
- 前端多层回调问题解决方案之$.Deferred
			javascript引擎是单线程的,但是通过异步回调可以实现IO操作并行执行能力,当业务逻辑复杂的时候我们就进入回调地狱. 本文讲得ajax是在jquery1.5以前的版本,目的旨在让我们理解延迟对象 ... 
- 51Nod 最大子矩阵和  | DP
			Input 第1行:M和N,中间用空格隔开(2 <= M,N <= 500). 第2 - N + 1行:矩阵中的元素,每行M个数,中间用空格隔开.(-10^9 <= M[i] < ... 
- asyncio  Lock,Queue
			# # total = 0 # # async def add(): # #1. dosomething1 # #2. io操作 # # 1. dosomething3 # global total ... 
- 【POJ】1830 开关问题(高斯消元)
			http://poj.org/problem?id=1830 高斯消元无解的条件:当存在非法的左式=0而右式不等于0的情况,即为非法.这个可以在消元后,对没有使用过的方程验证是否右式不等于0(此时因为 ... 
- 【51NOD-0】1089 最长回文子串 V2(Manacher算法)
			[算法]回文树 #include<cstdio> #include<algorithm> #include<cstring> using namespace std ... 
- Spring理论基础-控制反转和依赖注入
			第一次了解到控制反转(Inversion of Control)这个概念,是在学习Spring框架的时候.IOC和AOP作为Spring的两大特征,自然是要去好好学学的.而依赖注入(Dependenc ... 
- setTimeout()和setInterval()方法的区别
			setTimeout(); //5秒后执行yourFunction(),只执行一次 setInterval(); //每隔5秒执行一次 1.setTimeout(funhander,time)的作用是 ... 
