说明:设计模式系列文章是读刘伟
所著《设计模式的艺术之道(软件开发人员内功修炼之道)》
一书的阅读笔记。我的感受这本书讲的不错,有兴趣推荐读一读。详细内容也能够看看此书做者的博客https://blog.csdn.net/LoveLion/article/details/17517213
java
工厂模式
是最经常使用的一类建立型设计模式,一般咱们所说的工厂模式是指工厂方法模式
,它也是使用频率最高的工厂模式。简单工厂模式
是工厂方法模式的“小弟”,它不属于GoF23种设计模式,但在软件开发中应用也较为频繁,一般将它做为学习其余工厂模式的入门。此外,工厂方法模式还有一位“大哥”——抽象工厂模式
。这三种工厂模式各具特点,难度也逐个加大,在软件开发中它们都获得了普遍的应用,成为面向对象软件中经常使用的建立对象的工具。编程
简单工厂模式并不属于GoF 23个经典设计模式,但一般将它做为学习其余工厂模式的基础,它的设计思想很简单。设计模式
简单工厂模式(Simple Factory Pattern)
:定义一个工厂类,它能够根据参数的不一样返回不一样类的实例,被建立的实例一般都具备共同的父类。由于在简单工厂模式中用于建立实例的方法是静态(static)方法,所以简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类建立型模式。框架
简单工厂模式的要点在于:当你须要什么,只须要传入一个正确的参数,就能够获取你所须要的对象,而无须知道其建立细节。ide
简单工厂模式结构图以下所示:工具
在使用简单工厂模式
时,首先须要对产品类
进行重构,不能设计一个一应俱全的产品类,而需根据实际状况设计一个产品层次结构,将全部产品类公共的代码移至抽象产品类,并在抽象产品类中声明一些抽象方法,以供不一样的具体产品类来实现,典型的抽象产品类代码以下所示:学习
public abstract class Product { // 全部产品的公共属性 // 全部产品类的公共业务方法 public void methodSame() { //公共方法的实现 } // 声明抽象业务方法 public abstract void methodDiff(); }
在具体产品类
中实现了抽象产品类中声明的抽象业务方法。this
public class ConcreteProduct extends Product { @Override public void methodDiff() { // 具体产品业务方法的实现 } }
简单工厂模式的核心是工厂类
,在没有工厂类以前,客户端通常会使用new
关键字来直接建立产品对象,而在引入工厂类以后,客户端能够经过工厂类来建立产品,在简单工厂模式中,工厂类提供了一个静态工厂方法供客户端使用,根据所传入的参数不一样能够建立不一样的产品对象,典型的工厂类代码以下所示:.net
public class Factory { //静态工厂方法 public static Product getProduct(String arg) { Product product = null; if (arg.equalsIgnoreCase("A")) { product = new ConcreteProductA(); //初始化设置product } else if (arg.equalsIgnoreCase("B")) { product = new ConcreteProductB(); //初始化设置product } return product; } }
在客户端
代码中,咱们经过调用工厂类的工厂方法便可获得产品对象,典型代码以下所示:设计
public class Client { public static void main(String[] args) { Product product; product = Factory.getProduct("A"); //经过工厂类建立产品对象 product.methodSame(); product.methodDiff(); } }
有时候,为了简化简单工厂模式,咱们能够将抽象产品类
和工厂类
合并,将静态工厂方法移至抽象产品类中,以下图所示。
客户端能够经过产品父类的静态工厂方法,根据参数的不一样建立不一样类型的产品子类对象,这种作法在JDK等类库和框架中也普遍存在。
好比:java.nio.charset.Charset
public abstract class Charset { /** * Returns a charset object for the named charset. */ public static Charset forName(String charsetName) { java.nio.charset.Charset cs = lookup(charsetName); if (cs != null) return cs; throw new UnsupportedCharsetException(charsetName); } }
简单工厂模式提供了专门的工厂类用于建立对象,将对象的建立和对象的使用分离开,它做为一种最简单的工厂模式在软件开发中获得了较为普遍的应用。
使用场景:
简单工厂模式
虽然简单,但存在一个很严重的问题。当系统中须要引入新产品时,因为静态工厂方法经过所传入参数的不一样来建立不一样的产品,这一定要修改工厂类的源代码,将违背“开闭原则”,如何实现增长新产品而不影响已有代码?工厂方法模式应运而生。
在工厂方法模式
中,咱们再也不提供一个统一的工厂类来建立全部的产品对象,而是针对不一样的产品提供不一样的工厂,系统提供一个与产品等级结构对应的工厂等级结构。工厂方法模式定义以下:
工厂方法模式(Factory Method Pattern)
:定义一个用于建立对象的接口,让子类决定将哪个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称做虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类建立型模式。
工厂方法模式提供一个抽象工厂接口来声明抽象工厂方法,而由其子类来具体实现工厂方法,建立具体的产品对象。工厂方法模式结构如图所示:
在工厂方法模式结构图中包含以下几个角色:
与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂能够是接口,也能够是抽象类或者具体类,其典型代码以下所示:
public interface Factory { Product factoryMethod(); }
在抽象工厂中声明了工厂方法但并未实现工厂方法,具体产品对象的建立由其子类负责,客户端针对抽象工厂编程
,可在运行时再指定具体工厂类,具体工厂类实现了工厂方法,不一样的具体工厂能够建立不一样的具体产品,其典型代码以下所示:
public class ConcreteFactory implements Factory { @Override public Product factoryMethod() { return new ConcreteProduct(); } }
在客户端代码中,只需关心工厂类便可,不一样的具体工厂能够建立不一样的产品,典型的客户端类代码片断以下所示:
public class Client { public static void main(String[] args) { // 肯定是哪一个工厂可获得产品 Factory factory = new ConcreteFactory(); // 获取产品 Product product = factory.factoryMethod(); } }
有时候,为了进一步简化客户端的使用,还能够对客户端隐藏工厂方法,此时,在工厂类中将直接调用产品类的业务方法,客户端无须调用工厂方法建立产品
,直接经过工厂便可使用所建立的对象中的业务方法。
// 改成抽象类 public class AbstractFactory { // 在工厂类中直接调用产品类的业务方法 public void productMethod() { Product product = this.createProduct(); product.method(); } public abstract Product createProduct(); }
经过将业务方法的调用移入工厂类,能够直接使用工厂对象来调用产品对象的业务方法,客户端无须直接调用工厂方法,在客户端并不关心Product细节的状况下使用这种设计方案会更加方便。
工厂方法模式可以让工厂能够自主肯定建立何种产品对象,而如何建立这个对象的细节则彻底封装在具体工厂内部,用户只须要关心所需产品对应的工厂,无须关心建立细节,甚至无须知道具体产品类的类名。基于工厂角色
和产品角色
的多态性设计是工厂方法模式的关键。
工厂方法模式
经过引入工厂等级结构,解决了简单工厂模式中工厂类职责过重的问题,但因为工厂方法模式中的每一个工厂只生产一类产品,可能会致使系统中存在大量的工厂类,势必会增长系统的开销。此时,咱们能够考虑将一些相关的产品组成一个产品族
,由同一个工厂来统一辈子产,这就是咱们本文将要学习的抽象工厂模式的基本思想。
这里我斗胆举个例子来讲明一下吧,若是不恰当欢迎指出。
众所周知,国内知名的电器厂有海尔、海信(姑且就认为是2个),电器厂会生产电视机、电冰箱、空调(姑且就认为是3种产品)。
海尔电视机厂
、海尔电冰箱厂
、海尔空调厂
、海信电视机厂
、海信电冰箱厂
、海信空调厂
海尔工厂
、海信工厂
就够了,每一个工厂可生产自家的电视机、电冰箱、空调。由此看出使用抽象工厂模式
极大地减小了系统中类的个数。
抽象工厂模式为建立一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不仅是建立一种产品,它负责建立一族产品。抽象工厂模式定义以下:
抽象工厂模式(Abstract Factory Pattern):提供一个建立一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象建立型模式。
在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不一样类型的产品,这些产品构成了一个产品族,抽象工厂模式结构如图所示:
在抽象工厂模式结构图中包含以下几个角色:
在抽象工厂中声明了多个工厂方法,用于建立不一样类型的产品,抽象工厂能够是接口,也能够是抽象类或者具体类,其典型代码以下所示:
public abstract class AbstractFactory { public abstract AbstractProductA createProductA(); public abstract AbstractProductB createProductB(); public abstract AbstractProductC createProductC(); }
具体工厂实现了抽象工厂,每个具体的工厂方法能够返回一个特定的产品对象,而同一个具体工厂所建立的产品对象构成了一个产品族。对于每个具体工厂类,其典型代码以下所示:
public class ConcreteFactory1 extends AbstractFactory { @Override public AbstractProductA createProductA() { return new ConcreteProductA1(); } @Override public AbstractProductB createProductB() { return new ConcreteProductB1(); } @Override public AbstractProductC createProductC() { return new ConcreteProductC1(); } }
若是一开始就学习抽象工厂模式
估计很难理解为何这样设计,按次序学习分析简单工厂模式
、工厂方法模式
、抽象工厂模式
基本就瓜熟蒂落了。实际开发中,可能并非照搬照套工厂模式三兄弟的伪代码,大多会简化其中的部分实现。原本学习设计模式就是重思想,学习如何用抽象类、接口、拆分、组合等将软件解耦合,并加强系统可扩展性,这才是最关键的。