一.名称
体现了:依赖倒置,开放封闭,单一职责,接口隔离,迪米特法则,里氏替换原则。体现了所有的设计原则。
抽象类和继承——依赖倒置
抽象类——开闭原则
类间解耦——迪米特原则
抽象类——里氏替换原则
工厂方法模式主要通过增加抽象层来实现解耦。这个是这个模式的核心。
二.问题(为了解决什么问题)
- 提升扩展性,就可以考虑工厂模式,异构项目间使用工厂模式,可以屏蔽底层变化。
- 客户端只知道传入工厂类的参数,对于如何创建对象的具体过程并不关心。
三.解决方案(主要体现在uml和核心代码上)
在java中,有以下几种方式来创建对象:
1. 使用new关键字直接创建对象
2. 通过反射机制创建对象
3. 通过clone方法创建对象
4. 通过工厂类创建对象
毫无疑问,在客户端代码中使用new关键字是最简单的一种创建对象的方式,但是它的灵活性较差,工厂类的引入将降低因为产品或工厂类改变所带来的维护工作量。
类图
代码:简单
说明:
是否需要为设计中的每一个类都配备一个工厂类?答案是:具体情况具体分析。如果产品类很简单,而且不存在太多变数,其构造过程也很简单,此时无须为其提供工厂类。
此外,工厂模式还可以与模板方法模式、单例模式、原型模式等混合使用,变换出无穷优秀的设计,这也正是软件设计和开发的乐趣所在。
延伸-简单工厂模式
简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂又被称为静态工厂方法模式。
延伸-延迟初始化
即工厂类内部增加一个map集合,来存储已经实例化的产品,这样下次再使用该产品的时候就不用初始化了。
public class ProductFactory {
private static final Map<String, Product> preMap = new HashMap<>();
public static synchronized Product createProduct(String type) throws Exception {
Product product = null;
if (preMap.containsKey(type)) {
product = preMap.get(type);
} else {
if (type.equals("Procuct1")) {
product = new Product1();
} else {
product = new Product2();
}
preMap.put(type, product);
}
return product;
}
}
延迟初始化框架是可以扩展的,例如限制某个产品类的最大实例化数量,可以通过判断Map中已有的对象数量来实现,这样的处理是非常有意义的,例如jdbc连击数据库,都会要求设计一个最大连接量,该数量就是内存中最大实例化的数量。
四.效果(有啥优缺点)
优点:
1.将对象的创建和使用分离开
缺点:
1.增加了类的个数,以及系统的复杂度和理解难度
常见案例
简单工厂模式
图表库的设计。xxx公司欲基于java语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图表,例如柱状图、饼状图、折线图等。xxx公司图表库设计人员希望为应用系统开发人员提供一套灵活易用的图表库,而且可以较为方便的对图表库进行扩展,以便能够在将来增加一些新类型的图表。
图形库设计。使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形和三角形等)的绘制工具,每个几何图形都具有绘制draw和erase两个方法,要求在绘制不支持的形状时,提示一个UnSupportShapeException。
工厂方法模式
系统运行日志记录器。该记录日志支持多种途径保存,例如文件、数据库等。
图片读取器。针对每一种图片格式都设计一个图片读取器,例如,gif图片读取器用于读取gif格式的图片,jpg图片读取器用于赌气jpg格式的图片…