参考文档:
引言
1)还没有工厂时代:
假如还没有工业革命,如果一个客户要一款车,一般的做法是客户去创建一款车,然后拿来用。
2)简单工厂模式:
后来出现工业革命。用户不用去创建车。因为客户有一个工厂来帮他创建车.想要什么车,这个工厂就可以建。
比如想要宝马车。工厂就创建宝马车。即工厂可以创建产品。
3)工厂方法模式时代:
为了满足客户,车的种类越来越多,如宝马,奔驰,法拉利等一个工厂无法创建所有的车。
于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。
但是工厂还是个抽象。你需要指定某个具体的工厂才能生产某种车出来。
4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。
最终是客户只要对宝马的销售员说:我要宝马空调车,销售员就直接给他宝马空调车了。而不用自己去创建宝马空调车车.
这就是工厂模式
简单工厂模式(不属于23种设计模式)
含义:
- 简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法)
- 现实生活中,工厂是负责生产产品的;同样在设计模式中,简单工厂模式我们可以理解为负责生产对象的一个类,称为“工厂类”。
解决的问题:
- 将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦
模式组成:
uml类图:
优点:
- 将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦
- 把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程
缺点:
- 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响
- 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂
- 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构
举个栗子:
定义抽象产品
interface ICar { void start(); }
定义具体产品
class BenzCar implements ICar { @Override public void start() { System.out.println("im benz im starting .."); } }
定义具体产品
class BmwCar implements ICar { @Override public void start() { System.out.println("im bmw im starting .."); } }
定义工厂类
class CarFactory { public static ICar getCar(CarType type) { switch (type) { case BenzCarType: return new BmwCar(); case BmwCarType: return new BenzCar(); default: throw null; } } } enum CarType { BenzCarType, BmwCarType; }
客户端调用
ICar car=CarFactory.getCar(CarType.BenzCarType);
car.start();
输出
工厂方法模式
含义:
- 工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
解决的问题:
工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点
uml类图:
模式组成:
优点:
- 更符合开-闭原则 :新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
- 符合单一职责原则:每个具体工厂类只负责创建对应的产品
- 不使用静态工厂方法,可以形成基于继承的等级结构
总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
缺点:
- 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度
- 虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类
- 一个具体工厂只能创建一种具体产品
举个栗子:
定义抽象产品
interface ICar { void start(); }
定义具体产品
class BenzCar implements ICar { @Override public void start() { System.out.println("im benz im starting .."); } } class BmwCar implements ICar { @Override public void start() { System.out.println("im bmw im starting .."); } }
定义抽象工厂
interface ICarFactory { ICar createCar(); }
定义具体工厂
class BenzCarFactory implements ICarFactory{ @Override public ICar createCar() { return new BenzCar(); } } class BmwCarFactory implements ICarFactory{ @Override public ICar createCar() { return new BmwCar(); } }
客户端调用
public static void main(String[] args) { ICarFactory factory=new BenzCarFactory(); ICar benz=factory.createCar(); benz.start(); }
抽象工厂模式(Abstract Factory Pattern)
定义:
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类
解决的问题:
- 每个工厂只能创建一类产品。即工厂方法模式的缺点。
uml类图:
模式组成:
优点:
- 降低耦合。 抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
- 更符合开-闭原则。新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
- 符合单一职责原则。每个具体工厂类只负责创建对应的产品
- 不使用静态工厂方法,可以形成基于继承的等级结构。
缺点:
- 抽象工厂模式很难支持新种类产品的变化。
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则
举个栗子:
定义抽象产品
interface ICar { void start(); } //发动机 interface IEngine { String getName(); } //空调 interface IAirConditioner{ String getName(); }
定义具体产品
//奔驰系列发动机 class BenzEngine implements IEngine { @Override public String getName() { return "benz engine"; } } //奔驰系列空调 class BenzAirConditioner implements IAirConditioner { @Override public String getName() { return "benz AirConditioner"; } } //奔驰 class BenzCar implements ICar { IEngine engine; IAirConditioner airConditioner; public BenzCar(ICarFactory factory){ this.engine=factory.createEngine(); this.airConditioner=factory.createAirConditioner(); } public IAirConditioner getAirConditioner() { return airConditioner; } public void setAirConditioner(IAirConditioner airConditioner) { this.airConditioner = airConditioner; } public IEngine getEngine() { return engine; } public void setEngine(IEngine engine) { this.engine = engine; } @Override public void start() { System.out.println("im benz my engine is:"+engine.getName()+" my airconditionner is:"+airConditioner.getName()); } }
定义抽象工厂
interface ICarFactory { IAirConditioner createAirConditioner(); IEngine createEngine(); }
定义具体工厂
class BenzCarFactory implements ICarFactory { @Override public IEngine createEngine() { return new BenzEngine(); } @Override public IAirConditioner createAirConditioner() { return new BenzAirConditioner(); } }
客户端调用
public static void main(String[] args) { ICarFactory factory = new BenzCarFactory(); BenzCar benz=new BenzCar(factory); benz.start(); }