创建型模式之工厂模式
GitHub地址:https://github.com/zhangboqing/design-mode/tree/master/src/main/java/com/zbq
一、工厂模式分类
1)简单工厂
2)工厂方法
3)抽象工厂
二、简单工厂
1.定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
2、模式结构成员构成
• Factory:工厂角色
• AbstractProduct:抽象产品
• Product:具体产品
3.代码示例
1 /** 2 * @author zhangboqing 3 * @date 2017/12/12 4 * 简单工厂 5 */ 6 public class SimpleFactory { 7 8 /** 9 * 第一种形式 10 * 调用指定方法,直接返回对象 11 * @return 12 */ 13 public static Object createObject() { 14 15 return new Object(); 16 } 17 18 /** 19 * 第二种形式 20 * 根据指定的type,获取对应的对象 21 * @param type 22 * @return 23 */ 24 public static Object createObject(Integer type) { 25 26 if (type.equals(1)) { 27 return new Object1(); 28 } else if (type.equals(2)) { 29 return new Object2(); 30 } else if (type.equals(3)) { 31 return new Object3(); 32 } 33 return null; 34 } 35 36 37 /** 方便阅读,具体产品,放入同一个类 */ 38 public static class Object1 { 39 40 private static String name = "对象1"; 41 } 42 43 public static class Object2 { 44 private static String name = "对象2"; 45 } 46 47 public static class Object3 { 48 private static String name = "对象3"; 49 50 } 51 52 }
4.优点和缺点分析
优点:
>工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任
>客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量
>通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
缺点:
>系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护
>简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构
5.应用场景
在以下情况下可以使用简单工厂模式:
>工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
>客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
三、工厂方法
1.定义
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
2、模式结构成员构成
• Product:抽象产品
• ConcreteProduct:具体产品
• Factory:抽象工厂
• ConcreteFactory:具体工厂
3.代码示例
1 /** 2 * @author zhangboqing 3 * @date 2017/12/12 4 * 工厂方法 5 */ 6 public abstract class FactoryMethod { 7 8 //TODO:该方法就是工厂方法 9 public abstract Object createObject(String type); 10 11 12 /** 方便阅读,具体工厂实现类,放入同一个类 */ 13 public class FactoryMethod1 extends FactoryMethod { 14 15 //子类必须实现抽象工厂方法,决定到底生产哪个对象 16 @Override 17 public Object createObject(String type) { 18 //生成 19 return new Object1(); 20 } 21 } 22 23 public class FactoryMethod2 extends FactoryMethod { 24 25 //子类必须实现抽象工厂方法,决定到底生产哪个对象 26 @Override 27 public Object createObject(String type) { 28 //生成 29 return new Object2(); 30 } 31 } 32 33 public class FactoryMethod3 extends FactoryMethod { 34 35 //子类必须实现抽象工厂方法,决定到底生产哪个对象 36 @Override 37 public Object createObject(String type) { 38 //生成 39 return new Object3(); 40 } 41 } 42 43 44 /** 方便阅读,具体产品,放入同一个类 */ 45 public static class Object1 { 46 47 private static String name = "对象1"; 48 } 49 50 public static class Object2 { 51 private static String name = "对象2"; 52 } 53 54 public static class Object3 { 55 private static String name = "对象3"; 56 57 } 58 }
4.优点和缺点分析
优点:
>基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
>使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
缺点:
>在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
5.应用场景
在以下情况下可以使用工厂方法模式:
>一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
>一个类不知道它所需要的对象的类,将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
三、抽象工厂
1.定义
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
2、模式结构成员构成
• AbstractFactory:抽象工厂
• ConcreteFactory:具体工厂
• AbstractProduct:抽象产品
• Product:具体产品
3.代码示例
1 /** 2 * @author zhangboqing 3 * @date 2017/12/12 4 * <p> 5 * 抽象工厂 6 */ 7 public interface AbstractFactory { 8 9 //TODO:抽象工厂,由多个工厂方法组成 10 11 public Object createObject1(); 12 13 public Object createObject2(); 14 15 public Object createObject3(); 16 17 18 /** 19 * 方便阅读,具体工厂实现类,放入同一个类 20 */ 21 public class AbstractFactory1 implements AbstractFactory { 22 23 @Override 24 public Object createObject1() { 25 return new Object1(); 26 } 27 28 @Override 29 public Object createObject2() { 30 return new Object2(); 31 } 32 33 @Override 34 public Object createObject3() { 35 return new Object3(); 36 } 37 } 38 39 /** 40 * 方便阅读,具体产品,放入同一个类 41 */ 42 public static class Object1 { 43 44 private static String name = "对象1"; 45 } 46 47 public static class Object2 { 48 private static String name = "对象2"; 49 } 50 51 public static class Object3 { 52 private static String name = "对象3"; 53 54 } 55 }
4.优点和缺点分析
优点:
>当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
>增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
>在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
5.应用场景
在以下情况下可以使用抽象工厂模式:
>系统中有多于一个的产品族,而每次只使用其中某一产品族。
>属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
>系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。