工厂模式
主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
1 普通创建对象:
public class BMW320 { public BMW320(){ System.out.println("制造-->BMW320"); } } public class BMW523 { public BMW523(){ System.out.println("制造-->BMW523"); } } public class Customer { public static void main(String[] args) { BMW320 bmw320 = new BMW320(); BMW523 bmw523 = new BMW523(); } }
2 简单工厂模式:
产品类:
产品抽象类和具体子类
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。具体产品角色:工厂类所创建的对象就是此角色的实例。
package com.duoduo.Factory; public class BWV { public BWV() { } }
public class BWV888 extends BWV{ public BWV888() { System.out.println("This is a BWV888 car ~"); } }
public class BWV520 extends BWV{ public BWV520() { System.out.println("This is a BWV520 car~"); } }
工厂类:
本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品public class Factory { public static BWV createCar(int type) { switch(type) { case 520: return new BWV520(); case 888: return new BWV888(); default: break; } return null; } }
客户类:
public class Customer { public static void main(String [] args) { Factory ft=new Factory(); BWV bwv520=ft.createCar(520); BWV bwv888=ft.createCar(888); } }
开闭原则(对扩展开放;对修改封闭)
分析简单工厂模式:
产品部分:符合开闭原则
工厂部分:因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case),这显然是违背开闭原则的。
可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。
3 工厂方法模式:
工厂方法模式
去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。
这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
工厂方法模式组成:
1)抽象工厂角色: 工厂方法模式核心,与应用程序无关。是具体工厂角色必须实现的接口/继承的父类。在java中它由抽象类或者接口来实现。2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。
优点: 分担了对象承受的压力,使得结构变得灵活 起来
eg. 当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码.
抽象工厂:
package com.duoduo.Factory; public interface FactoryBWV { BWV createBWV(); }
具体工厂类:
public class FactoryBWV520 implements FactoryBWV{ @Override public BWV520 createBWV() { return new BWV520(); // TODO Auto-generated method stub } }
public class FactoryBWV888 implements FactoryBWV { @Override public BWV888 createBWV() { return new BWV888(); } }
产品类(抽象/具体):
public class BWV { public BWV() { } }
public class BWV888 extends BWV{ public BWV888() { System.out.println("This is a BWV888 car ~"); } }
public class BWV520 extends BWV{ public BWV520() { System.out.println("This is a BWV520 car~");
} }
客户类:
public class Customer { public static void main(String [] args) { FactoryBWV520 f1=new FactoryBWV520(); BWV520 b1=f1.createBWV(); FactoryBWV888 f2=new FactoryBWV888(); BWV888 b2=f2.createBWV(); // Factory ft=new Factory(); // BWV bwv520=ft.createCar(520); // BWV bwv888=ft.createCar(888); } }
分析:
当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。
4 抽象工厂模式:
需求改变:
随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。于是这个工厂开始生产空调和发动机,用来组装汽车。这时候工厂有两个系列的产品:空调和发动机。宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机。
解决方法:
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。
注意:
每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
产品类:(抽象/具体子类):
//发动机以及型号 public interface Engine { } public class EngineA implements Engine{ public EngineA(){ System.out.println("制造-->EngineA"); } } public class EngineB implements Engine{ public EngineB(){ System.out.println("制造-->EngineB"); } } //空调以及型号 public interface Aircondition { } public class AirconditionA implements Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); } } public class AirconditionB implements Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); } }
工厂类:
//创建工厂的接口 public interface AbstractFactory { //制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); } //为宝马320系列生产配件 public class FactoryBMW320 implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); } } //宝马523系列 public class FactoryBMW523 implements AbstractFactory { @Override public Engine createEngine() { return new EngineB(); } @Override public Aircondition createAircondition() { return new AirconditionB(); } }
客户类:
public class Customer { public static void main(String[] args){ //生产宝马320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); //生产宝马523系列配件 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); } }
总结:
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。