工厂设计模式概述:
实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
其实设计模式和面向对象设计原则都是为了使得 开发项目更加容易扩展和维护,解决方式就是一个“分工”。随着社会的发展,分工也越来越细。
原始社会的人,人什么都要会,自己种吃的,自己打猎,自己冷了,薅羊毛织衣服,自己治病等。现在社会出现了很多工厂,制造衣服的,制造食物的工厂,制造工具的工厂等。
首先我们看一下无工厂的模式:
上面代码在main方法所在的类中,创建者也是在此类中,如new BYD(),而调用者也在此类中,如a.run();即在次类中没有实现创建者和调用者的分离,既体现了创建又体现了调用,混在一起了。
简单工厂模式(不属于23种设计模式,相当于一个综合工厂):
简单工厂也叫静态工厂,就是工厂类一般使用静态方法,通过接受的参数的不同来返回不同的实例对象。
缺点:对于增加新产品,不修改代码的话,是无法扩展的。违反了开闭原则(对外扩展开放,对修改封闭)。比如你在工厂中准备一个新的车的品种宝马的话,就要修改工厂类中的代码。则破坏了代码。违反了开闭原则。
代码演示简单工厂模式:
package com.fan.domain3;
//第三步:调用者
public class CarTest {
public static void main(String[] args) {
//这里只体现独立的调用者
Car audi = CarFactory.getCar("奥迪");
audi.run();
Car byd = CarFactory.getCar("比亚迪");
byd.run();
}
}
//第一步:设计通用接口和两个实现类
interface Car{
void run();
}
//实现车的接口。这里相当于奥迪车图纸
class Audi implements Car {
public void run() {
System.out.println("奥迪在跑");
}
}
//实现车的接口,这里是比亚迪汽车图纸
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
}
//第二步:专门设计 一个工厂类 去制造汽车
//factory只是体现一个创建者。而不是调用者(使用者/消费者)
class CarFactory {
//方式一
public static Car getCar(String type){//传入汽车类型
if("奥迪".equals(type)){
return new Audi();//new 一个奥迪车
}else if("比亚迪".equals(type)){
return new BYD();//new 一个比亚迪车
}else{
return null;
}
}
//方式二:
/* public static Car getAudi(){
return new Audi();
}
public static Car getBYD(){
return new BYD();
}*/
}
图示:
总结:
这就是简单工厂方法,只有一个工厂类(一个大综合工厂)来面向多个目标实现。当目标实现增多时,我们不得不去修改工厂类的方法,使其兼容新的实现类型,这明显违背了开闭原则,所以出现了工厂方法模式。
工厂方法模式(属于23种设计模式,相当于多个细分的工厂):
工厂方法模式是对简单工厂模式的抽象升级,将工厂这个概念抽象出来成为接口,然后针对每种目标实现类创建一个工厂实现(细分工厂),一对一来实现,当新增了目标实现,只要同时新增一个工厂实现即可。
代码演示:
package com.fan.domain3;
//第三步:调用者
public class CarTest {
public static void main(String[] args) {
//这里只体现独立的调用者,
//创建工厂实例,然后调用工厂造汽车的方法
Car audi = new AudiFactory().getCar();
audi.run();
Car byd = new BydFactory().getCar();
byd.run();
}
}
//第一步:设计通用接口和两个实现类
interface Car{
void run();
}
//实现车的接口。这里相当于奥迪车图纸
class Audi implements Car {
public void run() {
System.out.println("奥迪在跑");
}
}
//实现车的接口,这里是比亚迪汽车图纸
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
}
//第二步:专门设计一个工厂的接口 和 具体的实现类工厂(细分工厂了)
interface CarFactory {
Car getCar();//车的工厂是专门用来获取汽车的。这是车工厂的规范
}
//接口就是用来被实现的,则下来我们需要有工厂接口的实现类 具体的工厂实现类
//奥迪汽车制造厂
class AudiFactory implements CarFactory {
public Car getCar() {//返回值类型也可以是Audi
return new Audi();
}
}
//BYD汽车制造厂
class BydFactory implements CarFactory {
public Car getCar() {//返回值类型也可以是BYD
return new BYD();
}
}
四、解析:
从上面的实例中可以很容易看出来,工厂方法模式的重点就在这个工厂接口了。
目标可以无限扩展,工厂类也要随之扩展,一对一存在,满足了开闭原则,但如果目标实现较多,工厂实现类也会增多,不简洁。
MyBatis中使用的比较多,事务模块和数据源模块都使用了工厂方法模式。
总结:
简单工厂模式与工厂方法模式真正的避免了代码的改动了吗,并没有。在简单工程模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将逻辑留在抽象工厂角色中,要么在客户端程序中将具体工厂角色写死(就像上面的例子一样,同样需要改代码从而来增加新工厂)。而且产品对象创建条件的改变必然会引起工厂角色的修改。
面对这种情况,java的反射机制与配置文件的巧妙结合突破了限制–这在spring中完美的体现出来。
抽象工厂模式 (属于23种设计模式)
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
抽象工厂与工厂方法的区别,就在于产品簇的问题,多了一种产品,这时候怎么办呢,就是在接口类里面加上创建大炮的方法,然后每个车间就可以有两个子车间分别来生产汽车和大炮。这样的话缺点也很显然的冒了出来,如果我又想生产飞机,那么我要需要更改所有的工厂车间以及工厂接口。
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
代码演示:
package com.fan.domain3;
//第三步:调用者
public class FactoryTest {
public static void main(String[] args) {
//这里只体现独立的调用者,
Car byd = new FactoryTwo().getCarByFactory();
byd.run();
Plane airPlan = new FactoryOne().getPlanByFactory();
airPlan.getPlane();
}
}
//第一步:设计第一个产品接口和两个实现类
interface Car{//车接口
void run();
}
//实现车的接口,这里相当于奥迪车图纸
class Audi implements Car {
public void run() {
System.out.println("奥迪在跑");
}
}
//实现车的接口,这里是比亚迪汽车图纸
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
}
//第二步:设计第二个产品接口 和 两个实现类
interface Plane {//飞机 接口
void getPlane();
}
class AirPlane implements Plane {
public void getPlane() {
System.out.println("客机在飞");
}
}
class BattlePlane implements Plane {
public void getPlane() {
System.out.println("战斗机在飞");
}
}
//第三步:抽象工厂接口 及 具体工厂实现类
interface Factory {
Car getCarByFactory();//
Plane getPlanByFactory();
}
//具体工厂类 1:可以生产奥迪 和 客机
class FactoryOne implements Factory {
public Car getCarByFactory() {
return new Audi();//生产奥迪
}
public Plane getPlanByFactory() {
return new AirPlane();//生产客机
}
}
//具体工厂类 2:可以生产比亚迪 和 战斗机
class FactoryTwo implements Factory {
public Car getCarByFactory() {
return new BYD();
}
public Plane getPlanByFactory() {
return new BattlePlane();
}
}
运行结果;
比亚迪在跑
客机在飞
总结:抽象工厂模式的用意是: 给客户端提供一个接口,可以创建多个产品族中的产品对象。
而且使用抽象工厂模式还要满足一定条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品。
2. 同属于同一个产品族的产品一起使用。