分类:
简单(静态)工厂模式
工厂方法模式
抽象工厂模式
简单(静态)工厂模式:
把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”
优点:
-
实现了对象创建和使用的分离;
-
客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可;
-
通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
-
工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响;
-
增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度;
-
系统扩展困难,一旦添加新产品不得不修改工厂逻辑;
-
由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展。
结构说明:
面向对象设计的基本原则:
1) OCP(开闭原则, Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。
2) DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程。
3) LoD(迪米特法则, Law of Demeter):只与你直接的朋友通信,而避免和陌生人通信。
简单(静态)工厂模式实现:
1、首先建立一个产品的抽象类
public abstract class INoodles { /** * 描述每种面条啥样的 */ public abstract void desc(); }
2、建立几种具体的产品类,继承抽象类
public class LzNoodles extends INoodles { @Override public void desc() { System.out.println("兰州拉面"); } } public class PaoNoodles extends INoodles { @Override public void desc() { System.out.println("泡面"); } } public class GankouNoodles extends INoodles { @Override public void desc() { System.out.println("干吃面"); } }
3、建立生产产品的工厂,专门负责创建对象
public class SimpleNoodlesFactory { public static final int TYPE_LZ = 1;//兰州拉面 public static final int TYPE_PM = 2;//泡面 public static final int TYPE_GK = 3;//干吃面 public static INoodles createNoodles(int type) { switch (type) { case TYPE_LZ: return new LzNoodles(); case TYPE_PM: return new PaoNoodles(); case TYPE_GK: default: return new GankouNoodles(); } } }
工厂方法模式定义:
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。
优点:
-
抽象化了简单工厂模式。再有新的需求进来时,不需要更改工厂的内容,符合了ocp原则。
-
可以一定程度上解耦,消费者和产品实现类隔离开,只依赖产品接口(抽象产品),产品实现类如何改动与消费者完全无关。
-
可以一定程度增加扩展性,若增加一个产品实现,只需要实现产品接口,修改工厂创建产品的方法,消费者可以无感知(若消费者不关心具体产品是什么的情况)。
-
可以一定程度增加代码的封装性、可读性。清楚的代码结构,对于消费者来说很少的代码量就可以完成很多工作。
-
另外,抽象工厂才是实际意义的工厂模式,工厂方法只是抽象工厂的一个比较常见的情况。
缺点:
-
每增加一个产品就要新增加一个相应的实例化工厂,增加了额外的开发量
结构说明:
工厂方法模式实现:
1、首先定义一个产品接口类,建立多个产品的生产实现
//抽象产品:动物类 interface Animal { public void show(); } //具体产品:马类 class Horse implements Animal { public Horse() { //构造具体产品:牛类 } public void show() { //具体产品:马类 } } //具体产品:牛类 class Cattle implements Animal { public Cattle() { //构造具体产品:牛类 } public void show() { //具体产品:牛类 } }
2、首先定义一个工厂接口,针对不同的产品实现不同工厂类进行生产
//抽象工厂:畜牧场 interface AnimalFarm { public Animal newAnimal(); } //具体工厂:养马场 class HorseFarm implements AnimalFarm { public Animal newAnimal() { System.out.println("新马出生!"); return new Horse(); } } //具体工厂:养牛场 class CattleFarm implements AnimalFarm { public Animal newAnimal() { System.out.println("新牛出生!"); return new Cattle(); } }
3、调用不同的工厂类生产不同的产品实例对象
满足了ocp原则,增加新的类需要修建新的工厂,增加了代码量,如果同时需要修改多个工厂类的时候会很麻烦,而简单工厂模式只需要修改一个类,工厂方法模式是升级版的简单工厂模式
//把各个工厂类进行bean注入,利用IOC控制反转通过工厂名来创建工厂类实例 // 从而创建对应的产品对象实例
抽象工厂模式定义:
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂是创建型设计模式,它强调了一系列相关产品对象(属于同一个产品族)的创建过程,它和工厂方法模式的侧重点不同,工厂方法模式更加侧重于同一产品等级,而抽象工厂模式侧重的是同一产品族。简单说就是一个工厂中生产的一系列对象都是同一个产品族的。
优点:
-
具体产品在应用层代码隔离,无须关心创建细节
-
将一系列的产品族统一到一起创建
缺点:
-
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
-
增加了系统的抽象性和理解难度
结构说明:
抽象工厂模式主要角色:
工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成
-
抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
-
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
-
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
-
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
抽象工厂模式实现:
1、创建Shape和Color具体产品类
public interface Shape { void draw(); } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } } public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } } public interface Color { void fill(); } public class Red implements Color { @Override public void fill() { System.out.println("Inside Red::fill() method."); } } public class Green implements Color { @Override public void fill() { System.out.println("Inside Green::fill() method."); } } public class Blue implements Color { @Override public void fill() { System.out.println("Inside Blue::fill() method."); } }
2、创建Shape和Color抽象工厂类和具体产品的工厂类
public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ; } public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } } public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); } else if(color.equalsIgnoreCase("GREEN")){ return new Green(); } else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } }
3、创建Shape和Color不同产品的产品构成的产品族,通过继承产品族抽象工厂类实现不同产品工厂构造器
public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } }
三种工厂模式之间的比较:
在简单工厂模式中,一个工厂类负责所有产品对象的创建,这个工厂类的职责大大增加,可能客户端对于某些产品的创建方式会有不同的要求,这样的话,就要不断的修改工厂类,增加相应的判断逻辑,不利于后期的代码维护。
另外,由于简单工厂模式使用静态方法创建,这就导致静态方法无法被继承(All Languages)。
所以,简单工厂模式适用于创建的对象比较少或简单的情况。
在工厂方法模式中,一个具体的工厂类负责创建一个单独的产品,如果有新的产品加进来,只需要增加一个具体的创建产品工厂类和具体的产品类就可以了,不会影响到已有的其他代码,代码量也不会变大,后期维护更加容易,增加了系统的可扩展性。
但是工厂方法模式无法体现产品之间的关系,如果有两个不同的产品需要创建,就需要两个不同的工厂类,即使这两个产品有某钟必要的联系,也还是需要两个不同的工厂类。
在抽象工厂模式中,一个具体的工厂类负责创建一系列相互关联的产品,当一系列相互关联的产品被设计到一个工厂类里后,客户端的调用变得非常简单;如果要更换这一系列的产品,只需要更换一个工厂类即可,但零件之间的组装如果放到客户端,则客户端变得非常臃肿,如果把零件之间的组装放在工厂类里,则又违反了工厂类单一职责的原则,使得工厂类既要负责对象的创建,又要负责产品的组装。
工厂模式在spring框架源码中的应用场景
1、Mybatis 使用SqlSessionFactoryBean 实现了 spring的FactoryBean。
在定义sqlSeeesionFactory时 ,实现类class不是自身的类,而是使用了SqlSessionFactoryBean工厂类,属于工厂模式。
SqlSeeesionFactoryBean 就是SqlSeeesionFactory的工厂Bean,是创建SqlSeeesionFactory 实例用的。
SqlSeeesionFactory 是SqlSeeesion得工厂,工厂就相当于一个容器。是创建、管理 SqlSeeesion用的。有了SqlSeeesion 就相当于有了Connection,这样接可以直接操作数据库了。
2、传统dao、service、controller的程序耦合性,spring利用工厂模式来进行解耦,bean的注入,通过反射来获取不同层的实例对象。