英语外贸网站建设,上海工商网查询企业信息查询系统,搜索附近的电子产品,wordpress作品集插件基于面向对象语言开发中#xff0c;免不得需要创建对象。前面讲解的单例模式也是如此#xff0c;不过是要创建唯一的对象。本文要讲述“工厂方法模式”是要封装创建对象的过程。工厂#xff0c;也称之为“制造厂”#xff0c;用于创建具体的产品直接提供给外界…基于面向对象语言开发中免不得需要创建对象。前面讲解的单例模式也是如此不过是要创建唯一的对象。本文要讲述“工厂方法模式”是要封装创建对象的过程。工厂也称之为“制造厂”用于创建具体的产品直接提供给外界使用。其实这就是对产品的创建过程的封装外界需要产品那就通过工厂提供的途径获取。反映到代码世界中如果对象的创建过程复杂需要封装对象创建过程时我们可不通过一个“工厂”来封装这个过程呢。工厂的具体代码表现形式要看封装的粒度。这里封装的粒度包括方法(代码块)、类。这二者也分别代表着简单工厂方法模式、工厂方法模式。
一、简单工厂模式
简单工厂模式即是对象创建过程的封装粒度为方法或代码块一般来说是方法。如下为一个创建汽车对象的工厂示例
/*** 汽车(抽象)接口*/
public interface Car {void start();void stop();
}/*** 普通汽车实现类*/
public class CommonCar implements Car{Overridepublic void start() {System.out.println(SUV 启动...);}Overridepublic void stop() {System.out.println(SUV 停止...);}
}/*** 创建汽车对象的工厂*/
public class CarFactory {public static Car createCarFactory() {return new CommonCar();}
}public class Client {public static void main(String[] args) {// 获取对象Car caInstance CarFactory.createCarFactory(); // 封装了所需对象创建的过程// 执行对象活动caInstance.start();caInstance.stop();}
}简单工厂模式的实现方法及类图如上用户端只需要通过CarFactory调用对应的方法即可获取对象不需要感知到对象的创建过程。在大部分的业务代码中还真就这种模式使用居多比如某数据库客户端对象的获取、某加密算法对象获取等。但是这么模式仅使用于比较简单的场景如果业务上需要有多种数据库客户端、多种加密算法时简单工厂方法模式就不能很好的胜任了。比如上述场景的汽车对象会区分SUV及小轿车。那工厂方法模式就必须得改动如改动为
public static Car createCarFactory(String type) {if (type.equalsIgnoreCase(sedan)) {return new Sedan(); // 创建轿车的逻辑} else if (type.equalsIgnoreCase(suv)) {return new SUV(); // 创建SUV的逻辑} else {throw new IllegalArgumentException(无效的汽车类型 type);}}这样一改就有两个缺点① 工厂方法逻辑完全改变了也需要求客户端(上游依赖方)跟着改动② 随着汽车种类的增多if判断条件也会增加。多种类型汽车初始化逻辑存在于一个方法内部非常不利于代码维护、调试。因此简单工厂模式的最大缺点就是不易扩展。进一步说不易扩展的根因就在于将对象的创建逻辑封装与单一方法内部不符合单一职责原则也肯定不满足开闭原则了。 简单工厂模式的优点
避免对象创建过程的暴露实现简单实用性高。适合创建对象种类少、规则相对稳定的业务。
简单工厂模式的优点
不符合单一职责原则工厂创建对象的方法职责过重。不符合开闭原则增加对象种类需要改动原有工厂方法甚至需要上游跟随改动。
二、工厂方法模式
为应用多种对象创建的需求设计的工厂模式必须符合开闭原则。基于依赖倒置设计原则工厂模块也应该有其抽象类工厂与产品之间通过抽象类进行相互依赖。对于不同的抽象类用于创建不同的产品实例因此客户端仅需要感知创建那种对象使用那种工厂和生活中例子一样需要造汽车就找汽车工厂需要衣服就找制服厂等。 还是以上述例子为例如何实现SUV汽车、轿车的工厂代码如下 ① 汽车接口
public interface Car {void start();void stop();
}② 汽车具体实现类
public class SUV implements Car{Overridepublic void start() {System.out.println(SUV 启动...);}Overridepublic void stop() {System.out.println(SUV 停止...);}
}public class Sedan implements Car{Overridepublic void start() {System.out.println(轿车 启动...);}Overridepublic void stop() {System.out.println(轿车 启动...);}
}③ 工厂接口
public interface Factory {Car createCarInstance();
}④ 工厂具体实现类
public class SUVFactory implements Factory{Overridepublic Car createCarInstance() {return new SUV();}
}public class SedanFactory implements Factory{Overridepublic Car createCarInstance() {return new Sedan();}
}⑤ 客户端
public class Client {public static void main(String[] args) {SUVFactory suvFactory new SUVFactory();Car car4SUV suvFactory.createCarInstance(); // 创建SUV汽车实例SedanFactory sedanFactory new SedanFactory();Car car4Sedan sedanFactory.createCarInstance(); // 创建SUV汽车实例}
}工厂方法模式的示例代码及类图如上所示这种设计模式解耦了工厂与产品的关系。高层与底层模块的关系符合依赖倒置原则类之间的关系也符合迪米特法则。不同具体工厂类负责不同产品的实例创建因此符合单一职责原则。从后续业务发展来看即使后续增加产品类型也只是增加新的产品类及对应的产品工厂类不会改变已有的业务逻辑因此这个设计方案是符合开闭原则的。 工厂方法模式的优点
避免对象创建过程的暴露符合开闭原则易扩展适合创建对象种类多、规则相对不稳定的业务。
工厂方法模式的优点
实现负责容易造成类的激增。
三、后注
本篇文章讲解了简单工厂模式以及工厂方法模式这里我想说下工厂设计模式的宏观理解。简单的创建对象流程即使客户端直接创建对象然后使用。 这个是最简单的创建并使用对象的方法也是最常见的。但是问题在于如果对象的创建过程及其复杂难道要所有的调用方均复制一遍这块代码增加了系统代码的臃肿程度。 因此对于创建过程我们可以使用一种方式封装起来。封装在面向对象设计中就是为了复用代码复用这套复杂创建逻辑的代码。封装的究极解决方案就是“加一层”也是大部分情况都能很好解决问题的方案。何为加一层就是在客户端与要创建对象的类之间加一层将创建初始化对象的逻辑封装到中间层-工厂。之后客户端要创建对象就找工厂将客户端与对象复杂的创建过程进行解耦。【这里的基本思路为是谁导致的问题找个人来负责解决它即是重要逻辑细化】【如何更好使用单一职责原则那块逻辑对业务影响大那就需要一个方法、类或模块来负责之】 因此创建对象这件事就仅是客户端和目标类之间的关系中间有个工厂需要介入。 负责封装目标对象的工厂模式的具体表现要根据目标对象的复杂程度而定复杂程度包括对象的种类数、对象业务规则的稳定性来确定。如果要创建的对象十分简单那就使用简单工厂模式即可反之则需要使用工厂方法模式来保证可扩展性。 提问会不会存在工厂也比较多的时候呢如何解决