工厂模式包括:
- 简单工厂
- 工厂方法
- 抽象工厂
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。工厂模式都是实现创建者和调用者分离,下面开始逐一介绍:
- 简单工厂模式
模式UML类图
角色分析
- Factory:工厂角色
- Product:抽象产品角色
- ConcreteProduct:具体产品角色
工厂角色(Creator) | 是简单工厂模式的核心,它负责实现创建所有具体产品类的实例。工厂类可以被外界直接调用,创建所需的产品对象。 |
抽象产品角色(Product) | 是所有具体产品角色的父类,它负责描述所有实例所共有的公共接 口 。 |
具体产品角色(Concrete Product) | 继承自抽象产品角色,一般为多个,是简单工厂模式的创建目标。工厂类返回的都是该角色的某一具体产品。 |
示例程序:通过汽车工厂生产汽车(奔驰和奥迪两种车型),消费者(客户端)只需要与汽车工厂联系(依赖)
示意图
代码实现
package Factory;
interface Car{
void run();
}
class Aodi implements Car{
@Override
public void run() {
System.out.println("我是奥迪汽车...");
}
}
class Benchi implements Car{
@Override
public void run() {
System.out.println("我是奔驰汽车...");
}
}
class CarFactory{
static public Car createCar(String name) {
Car car = null;
if(name.equals("奥迪")) {
car = new Aodi();
}else if(name.equals("奔驰")) {
car = new Benchi();
}
return car;
}
}
/**
* @author Moti
* @Time 2019年9月21日
*/
public class Main {
public static void main(String[] args) {
Car car = CarFactory.createCar("奔驰");
car.run();
}
}
分析简单工厂模式的优缺点
- 优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
- 缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。违反开闭原则 。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。
- 工厂方法模式
模式UML类图
每一个产品都有自己独立的工厂
角色分析
- 抽象产品(Product)
- 具体产品(Concrete Product)
- 抽象工厂(Factory)
- 具体工厂(Concrete Factory)
抽象产品(Product) | 具体产品的父类 描述具体产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 描述生产的具体产品 |
抽象工厂(Factory) | 具体工厂的父类 描述具体工厂的公共接口 |
具体工厂(Concrete Factory) | 抽象工厂的子类;被外界调用描述具体工厂;实现FactoryMethod工厂方法创建产品的实例 |
示例程序:通过奥迪汽车工厂或者奔驰汽车工厂生产汽车,消费者(客户端)只需要与汽车工厂联系(依赖)
示意图
实例程序UML类图
代码实现
1. 汽车的抽象类
package AbstractFactory;
/**
* 定义汽车的抽象类
* @author Moti
* @Time 2019年9月27日 下午3:04:23
*/
public abstract class Car {
public abstract void run();
}
2. 奥迪汽车类
package AbstractFactory;
/**
* 定义奥迪车,继承抽象类Car实现run方法
* @author Moti
* @Time 2019年9月27日 下午3:06:10
*/
public class Aodi extends Car {
@Override
public void run() {
System.out.println("我是奥迪车..滴滴滴..");
}
}
3. 奔驰汽车类
package AbstractFactory;
/**
* 定义奔驰车,继承抽象类Car实现run方法
* @author Moti
* @Time 2019年9月27日 下午3:07:29
*/
public class Benchi extends Car {
@Override
public void run() {
System.out.println("我是奔驰车..滴滴滴..");
}
}
4. 抽象汽车工厂的接口
package AbstractFactory;
/**
* 汽车工厂的接口,将具体实例的生成交给子类
* @author Moti
* @Time 2019年9月27日 下午3:08:35
*/
public interface CarFactory {
Car createCar();
}
5. 奥迪汽车工厂的类,实现了抽象汽车工厂接口
package AbstractFactory;
/**
* 定义奥迪车的工厂
* @author Moti
* @Time 2019年9月27日 下午3:09:53
*/
public class AodiCarFactory implements CarFactory {
@Override
public Car createCar() {
return new Aodi();
}
}
6. 奔驰汽车工厂的类,实现了抽象汽车工厂接口
package AbstractFactory;
/**
* 定义奔驰车的工厂
* @author Moti
* @Time 2019年9月27日 下午3:10:57
*/
public class BenchiCarFactory implements CarFactory {
@Override
public Car createCar() {
return new Benchi();
}
}
7. 客户端调用
package AbstractFactory;
/**
* @author Moti
* @Time 2019年9月27日 下午3:12:45
*/
public class Client {
public static void main(String[] args) {
CarFactory carFactory1 = new AodiCarFactory();
CarFactory carFactory2 = new BenchiCarFactory();
Car car1 = carFactory1.createCar();
Car car2 = carFactory2.createCar();
car1.run();
car2.run();
}
}
分析工厂方法模式的优缺点
- 优点
用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类名;所有的具体工厂类都具有同一抽象父类;符合开闭原则,新增产品只需要添加工厂类和具体产品,无需修改代码,扩展性好;
- 缺点
添加一个新的产品,系统中类的个数增加,导致增加了系统的复杂性,有更多的类需要编译和运行,会增加系统性能的开销;由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度;
- 抽象工厂模式
前言
- 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
- 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
- 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
产品等级:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
模式UML类图
这里,1号工厂(ConcreteFactory1)可以生产A,B,C三种产品(ConcreteProductA,B,C)
同样,2号工厂也可以生产A,B,C三种产品
那么1号工厂生产的这三种产品构成一个产品族,2号工厂生产的这三种产品也构成一个产品族.
1号工厂生产的A产品和2号工厂生产的A产品构成一个产品等级
1号工厂生产的B产品和2号工厂生产的B产品 构成一个产品等级
1号工厂生产的C产品和2号工厂生产的C产品 构成一个产品等级
角色分析
- 抽象产品(Product)
- 具体产品(Concrete Product)
- 抽象工厂(Factory)
- 具体工厂(Concrete Factory)
抽象产品(Product) | 具体产品的父类 描述具体产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 描述生产的具体产品 |
抽象工厂(Factory) | 具体工厂的父类 描述具体工厂的公共接口 |
具体工厂(Concrete Factory) | 抽象工厂的子类;被外界调用描述具体工厂;实现抽象工厂中创建产品的实例 |
示例程序:获得三种电子元件(RAM,CPU,Mouse),有日本工厂和中国工厂,这两个工厂都可以生产这三种电子元件
注意:这里日本工厂生产的所有产品构成一个产品族,中国工厂生产的所有产品也构成一个产品族,共两个产品族.示例程序中出现了两种RAM,两种CPU,两种Mouse(分别来自中国工厂和日本工厂),这些同种商品分类构成一个产品等级,也就是说有三个产品等级.
示例程序UML类图
代码实现
1.抽象产品和具体产品
//设备接口(产品的抽象)
public interface Device {
String getDeviceName();
}
//RAM(具体的产品)
public class RAM implements Device {
private String factoryName;
public RAM(String factoryName) {
this.factoryName = factoryName;
}
@Override
public String getDeviceName() {
return "获得"+factoryName+"生产的RAM";
}
}
//CPU(具体的产品)
public class CPU implements Device {
private String factoryName;
public CPU(String factoryName) {
this.factoryName = factoryName;
}
@Override
public String getDeviceName() {
return "获得"+factoryName+"生产的CPU";
}
}
//Mouse(具体的产品)
public class Mouse implements Device {
private String factoryName;
public Mouse(String factoryName) {
this.factoryName = factoryName;
}
@Override
public String getDeviceName() {
return "获得"+factoryName+"生产的Mouse";
}
}
2.抽象工厂和具体工厂
//抽象工厂
public interface DeviceFactory {
Device createCPU();
Device createARM();
Device createMouse();
}
//具体工厂
public class ChinaFactoy implements DeviceFactory {
@Override
public Device createCPU() {
return new CPU("中国");
}
@Override
public Device createARM() {
return new RAM("中国");
}
@Override
public Device createMouse() {
return new Mouse("中国");
}
}
//具体工厂
public class JapanFactory implements DeviceFactory{
@Override
public Device createCPU() {
return new CPU("日本");
}
@Override
public Device createARM() {
return new RAM("日本");
}
@Override
public Device createMouse() {
return new Mouse("日本");
}
}
3.客户端Client
public class Client {
public static void main(String[] args) {
DeviceFactory factory = new JapanFactory();
Device device = factory.createMouse();
String string = device.getDeviceName();
System.out.println(string);
}
}
分析抽象工厂模式的优缺点
- 优点
分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。
易于交换产品系列。一个具体工厂类只在初始化时出现一次,这使得改变一个应用的具体工厂变得很容易,只需改变具体的工厂即可使用不同的产品配置。
有利于产品的一致性。当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。
- 缺点
难以支持新种类的产品。因为抽象工厂接口确定了可以被创建的产品集合(产品族),所以难以扩展抽象工厂以生产新种类的产品。