【java】设计模式之工厂模式
来源:互联网 发布:手机唱歌调音软件 编辑:程序博客网 时间:2024/05/17 07:37
学设计模式,我们要知道这个设计模式是用来解决什么问题的,并且知道,所有设计模式的设计初衷都是为了让代码更加符合面向对象的原则。
但是对于像我这样工作经验不多的小白,面对一些设计模式的确很难想到相应的应用场景,尤其是对于刚毕业的大学生。这种情况下不如先看看它的代码。
工厂模式有简单工厂模式(静态工厂模式),工厂方法模式和抽象工厂模式。
首先是简单工厂模式,
定义:由一个对象决定实例化接口的哪一个子类。
(这里的“决定”,不是让对象决定,而是对象(的这个方法)有了实例化不同类的权利,就是说,代码写完,我都不一定知道实际运行时,工厂会产生什么对象,但是我赋予了它产生一类(接口的子类)对象的权利)
假设:这个社会有一个种产品,客户端购买,那么,我们可以这样写:
public class Product {private String name;public Product(String name) {this.name = name;}}
Product p = new Product();然后,社会进步了,这种产品出现了三个类型(第一种,第二种,第三种);
你可以这样写:
Product p1 = new Product(“first”);Product p2 = new Product(“second”);Product p3 = new Product(“third");
如果出现一万种,你的客户端是不是都这样写了呢?你发现问题了吗,既然客户端购买这个产品,当客户端又兼顾生产这种产品的职责(new Product())。
不如把这个工作,交给一个工厂,这个工厂负责生产不同的产品,而你只需要告诉他你要什么就好了,产品类的初始化交给它去做
这是类图
接口IProduct,public方法 show()。
public interface IProduct { public void show();}
下面有三个类,FirstProduct,SecondProduct,ThirdProduct。
就只贴一个吧。
public class FirstProduct implements IProduct {@Overridepublic void show() {System.out.println("第一个零件");}}
工厂类,Factory,它有一个静态方法,返回接入IProduct实例的make方法。(不要静态也行,客户端可以实例化一个工厂类,有了静态方法就不用实例化工厂类了)
public class Factory {public static IProduct make(int i) {if(i==1){return new FirstProduct() ;}if(i==2){return new SecondProduct() ;}if(i==3){return new ThirdProduct() ;}return null;}
测试类代码:
public static void main(String[] args) {IProduct product1 = Factory.make(1);IProduct product2 = Factory.make(2);IProduct product3 = Factory.make(3);product1.show();product2.show();product3.show();}
这样,类的初始化,由客户端,转移到工厂类里面。
如果不用接口,工厂想要生产这么多产品,必须针对每一个产品类,都要写一个方法,(改天写一篇面向接口编程的心得,推荐看head first 设计模式-工厂模式篇,它谈到需求改变,A a = new A()的不迎合变化的缺点,它认为简单工厂更像是一种编程习惯而非模式,事实上,简单工厂模式也非GOF的二十三种模式之一)
而且,夜不能放在一个方法里面。如果放在一个方法里面,返回类型是什么?所以,接口的出现,让这些类可以用同一个返回类型,这个返回类型就是“继承了这个借口的所有子类的类型”。
工厂模式的这一个点很重要——“延迟始化”(Lazy Initialization)。
延迟始化,顾名思义,延迟初始化,延迟产品类的初始化。
为什么要延迟初始化?很多情况下,我们需要在类初始化的时候,做一些事情,ok,我们可以把这些东西放到了这个类的构造方法里面,可是,有时候又需要处理另外一些情况怎么办?加判断条件,或者写约束。但这无疑加重的类的任务,增加了耦合度,这不符合我们的OO设计理念。
我们要处理的这些情况也不能交给客户端去做。所以,我们把这些事情,放到延迟初始化里面。
除此之外,还可以这样利用:在我们的类的实例可以重复利用的情况下,假如,这个类已经实例化过了, 何不返回一个已经产生的实例?
简单说一下,上面的代码没有写出。就是在工厂类里面,私有一个泛型为IProduct的arraylist,然后在make方法里面,判断一下,当前需要初始化的这个类有没有被初始化过,如果没有,那么初始化,存入arraylist,然后返回实例,如果有,直接从arraylist里面取出,返回。
当然,延迟始化还有很多作用,这里脑洞就不开太大了。我也突然发现我之前遇到的一些问题,可以用延迟始化来解决:比如,对不同类,不同情况下,初始化的处理,如果在每一个类自己的初始化里面做各种分析、条件判断,不仅找起来麻烦,找到也不好修改,不如都放在工厂的make方法下,便于处理,最起码代码好看多了,也方便。
亲娘来,我就是回顾一下以前学的东西,俩小时过去了。
推荐一本书《设计模式之禅》,真心不错。
顺带说一句,书这个东西嘛,没事多找几本自己可能会用到的书,存着,等哪天用到了查就好了,没有必要一口气看下来,你要是时间多,系统地看也无妨。
话说这些年我买的书,没有一本全看完的,都是看对当时的我有用的部分,或者 需要的时候查看一下。
无生也有涯,而知也无涯, 以有涯随无涯,岂不傻叉嘛。
接下来是 工厂方法模式。
定义:定义了一个创造对象的接口,由其子类决定实例化的类是哪一个。工厂方法让类把实例化推迟到了子类。
其实工厂方法模式就是在简单工厂模式之上,给工厂抽一个一个接口。
为啥么呢。假如,我们又有了新的产品,新的工厂,怎么办?在原有的工厂的make方法里加判断?这不符合OCP。
那么我们另起一个工厂。但是如果之后又加了新的产品、新的工厂,你能想象客户端乱七八糟的样子吗?
所以,所有工厂抽取一个工厂接口,这样,就符合OCP原则了。
这是类图,Factory1只生产Product1和Product2两种产品,Factory2只生产Product3这种产品,这样我们就不用修改原来的代码,从而让产品3进入市场了,嘿嘿。
public static void main(String[] args) {IFactory factoryA = new Factory1();IFactory factoryB = new Factory1();IProduct productA = factoryA.createProduct(1);productA.productMethdod();IProduct productB = factoryB.createProduct(3);productB.productMethdod();}这是“市场”(客户端)
或许你会说“这样看来,简单工厂模式并不完全符合OCP原则啊”。是啊,但是那也要看在什么情况下,如果产品是人类的话,区别产品的条件是性别,无非有 男、女、无性别、双性人这四种。在既有条件下,不会出现新的产品,那么简单工厂和工厂方法都符合OCP。你可能会想到:对啊现在有ABC三种商品,如果这些商品区分男女,或者用其他条件分类怎么办?这就是下面要说的-抽象工厂模式。
抽象工厂模式。
定义:为创建一组相关或相互依赖的对象,提供一个接口,且无需指明具体的对象。
在说抽象工厂之前,明确一个态度,那就是:提出设计模式是为了解决问题,但是,并不是说,给你一个问题,你绕过了设计模式寻求其他的方法,或许在这个问题面前,确实有其他的解决办法,但我们谈的是设计模式,所以就说设计模式。
假设:市面上有产品A ,产品B,工厂1能生产出男人用的A 和 B,而工厂2生产出女人用的 A 和 B。
在这里,要了解一个概念,产品族和产品等级结构。上述提到的,产品A和产品B,是属于同一个产品等级结构,但是男用AB和女用AB,就是不同的产品族。
类图:
产品接口IProductA和IProductB将产品分为2种,A和B。
工厂接口声明了两种方法,生产A和生产B。
因为要生产这两种的产品,所以工厂接口代码如下:
public interface IFactory {public IProductA makeProductA();public IProductB makeProductB();}
Factory1.java
public class Factory1 implements IFactory {@Overridepublic IProductA makeProductA() {return new ProductA1();}@Overridepublic IProductB makeProductB() {return new ProductB1();}}Factory2.java
public class Factory2 implements IFactory {@Overridepublic IProductA makeProductA() {return new ProductA2();}@Overridepublic IProductB makeProductB() {return new ProductB2();}}产品类就列出一个:
public class ProductA1 implements IProductA {@Overridepublic void show() {System.out.println("产品A1");}}test.java
public static void main(String[] args) {IFactory factory1 = new Factory1();IFactory factory2 = new Factory2();IProductA pA1 = factory1.makeProductA();IProductB pB1 = factory1.makeProductB();IProductA pA2 = factory2.makeProductA();IProductB pB2 = factory2.makeProductB();System.out.println("这是工厂1,生产:");pA1.show();pB1.show();System.out.println("这是工厂2,生产:");pA2.show();pB2.show();}
运行结果:
抽象工厂模式是针对多个产品等级结构,所以在工厂接口里,对与每一个产品接口,它都要有一个方法。或许你会问,那这样的话, 添加新种类的产品怎么办?工厂接口里是不是要修改呢?
是的,就是要修改,但是呢,有利就有弊,反之亦然。抽象工厂模式下,工厂是用来创造一个产品族的,而工厂方法模式下,工厂只是用来创造产品,不用考虑产品族的问题。
我们的目的是解耦,根据不同的情况,选择适合的模式。
- Java设计模式之工厂设计模式
- [java]设计模式之工厂设计模式
- Java设计模式之工厂设计模式
- Java设计模式之工厂设计模式
- JAVA设计模式之工厂设计模式
- java设计模式之工厂设计模式
- Java设计模式之工厂设计模式
- 《java设计模式》之工厂设计模式
- JAVA设计模式之工厂模式之简单工厂模式
- JAVA设计模式之工厂模式之工厂方法模式
- JAVA设计模式之工厂模式之抽象工厂模式
- Java设计模式之工厂
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- java设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- 集训队专题(3)1008 最短路
- iOS客户端的APNS服务简介与实现
- 集训队专题(3)1009 Choose the best route
- android控件——继承AdapterView的控件无法使用addView方法
- 第一篇csdn博客,随便写写
- 【java】设计模式之工厂模式
- 集训队专题(3)1010 Here We Go(relians) Again
- 温故指针一
- Qt for linux 安装
- Android使用TabLayout报错—— java.lang.NoClassDefFoundError
- 集训队专题(3)1011 Einbahnstrasse
- Android常见布局概览
- 集训队专题(3)1012 In Action
- UVa 227 Puzzles