Java设计模式笔记(3)工厂模式
1. 工厂模式简单介绍
工厂模式是一种创建对象的设计模式,它提供了一种方式来封装对象的创建逻辑,并根据不同的需求,返回相应的对象实例。工厂模式使得客户端代码与具体对象的创建过程解耦(将代码中的关联性和依赖性降低,使得各个模块之间的耦合度减少),提高了代码灵活性和可维护性。
总结:工厂模式是 通过封装对象创建的过程,提供了一种 统一的接口来创建对象。它隐藏了对象的具体实现细节,提供了灵活性、可扩展性,并提高了代码的可读性和可维护性。
2. 工厂模式目的
工厂模式的主要目的是解决以下问题:
- 将对象的创建逻辑与使用代码分离,使得使用代码不需要关心对象具体如何创建。(解耦)
- 提供一种简单的扩展机制,使得新增一种产品时不需要修改现有的代码,只需扩展工厂类即可。
工厂模式的核心思想是引入一个抽象的工厂接口或抽象类,该接口或抽象类定义了创建对象的方法,具体的对象创建由实现该接口或抽象类的具体工厂类来完成。
优点:
- 封装对象的创建过程:工厂模式将对象的创建过程封装在工厂类中,使得客户端无需关注对象的具体创建细节,只需通过工厂类获取所需对象。
- 解耦客户端与具体产品:客户端只需要通过工厂接口来创建对象,而无需直接实例化具体产品类,从而降低了客户端与具体产品的耦合度。
- 提供灵活性和可扩展性:通过新增具体工厂类和产品类,可以方便地扩展工厂模式,增加新的产品类型,而不需要修改已有代码。
- 代码可读性和可维护性:工厂模式提供了清晰的代码结构,使得代码更易于理解、维护和测试。
缺点:
- 增加了系统的复杂性:引入工厂类和抽象产品类会增加系统的类和对象数量,增加了系统的复杂性。
- 增加了开发的初期成本:工厂模式需要定义抽象工厂类和具体工厂类,以及相应的产品类,这在开发的初期会增加一定的开发成本。
- 难以支持新种类的产品:如果需要添加新种类的产品,除了新增具体产品类外,还需要修改抽象工厂接口和所有具体工厂类的实现,可能会导致较大的修改范围。
综上所述,工厂模式在提供灵活性、可扩展性和代码可读性方面具有优点,但也会增加系统的复杂性和开发成本。在设计时需要权衡使用工厂模式的利弊,并根据具体情况选择是否使用该模式。
3. 工厂模式分类
工厂模式包含很多,常见的三种分别是:
- 简单工厂模式(Simple Factory Pattern):简单工厂模式通过一个工厂类来封装对象的创建逻辑,根据客户端传入的参数返回相应的产品对象。
- 工厂方法模式(Factory Method Pattern):工厂方法模式将对象的创建延迟到子类中,每个具体子类都负责创建一个特定的产品对象,客户端通过调用工厂方法来获取所需的产品对象。
- 抽象工厂模式(Abstract Factory Pattern):抽象工厂模式提供一个接口或抽象类,用于创建一系列相关或相互依赖的产品对象。具体的工厂类实现了该接口或继承了该抽象类,并负责创建对应的产品系列。
下面以实现一个简单的画图功能来学习三大工厂模式
3.1 简单工厂模式
工厂类会根据不同的参数或条件来决定创建哪种对象,这样客户端只需要知道自己需要什么对象,而不需要关心对象的创建过程!
//定义产品接口 抽象产品类
public interface Shape {
void draw();
}
//实现产品接口 具体类 三角形
public class Triangle implements Shape {
@Override
public void draw() {
System.out.println("三角形实现类");
}
}
//实现产品接口 具体类 圆
public class Cricle implements Shape {
@Override
public void draw() {
System.out.println("圆实现类");
}
}
//实现产品接口 具体类 正方形
public class Square implements Shape {
@Override
public void draw() {
System.out.println("正方形实现类");
}
}
//简单工厂
public class ShapeFactory {
public static Shape CreateShap( String type) {
//equalsIgnoreCase比较不区分大小写
if(type.equalsIgnoreCase("circle")) {
return new Cricle();
}else if (type.equalsIgnoreCase("square")) {
return new Square();
}else if (type.equalsIgnoreCase("triangle")) {
return new Triangle();
}else {
return null;
}
}
}
public class Test {
public static void main(String[] args) {
Shape circle=ShapeFactory.CreateShap("circle");
circle.draw();
Shape square=ShapeFactory.CreateShap("square");
square.draw();
Shape triangle=ShapeFactory.CreateShap("triangle");
triangle.draw();
}
}
以上的代码就是遵循简单工厂模式设计的,它的核心思想就是:将对象的创建过程封装到工厂类中。简单工厂包含三部分:抽象产品类、具体产品类、具体工厂类。这里的抽象类,可以理解就是共有部分,比如图形类。这就是抽象类,他抽象了所有图形的一个合集。
- 具体工厂类: 这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
- 抽象产品类: 它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
- 具体产品类: 工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
简单工厂设计本身是不合规的,为什么这么说了?打个比方:如果我想要实现画另一个图形功能,那么我就要修改工厂类的代码。问题来了,开闭原则的概念:对扩展开放,对修改关闭
。我们修改了工厂类的源码,那么也就严重违反了开闭原则。为了解决这个存在的严重弊端,后来也就出现了工厂方法模式!
3.2 工厂方法模式
//抽象产品类
public interface Product {
public void operation();
}
//具体产品A
public class ProduceA implements Product {
@Override
public void operation() {
System.out.println("具体产品A生产!");
}
}
//具体产品B
public class ProduceB implements Product {
@Override
public void operation() {
System.out.println("具体产品B生产!");
}
}
//抽象工厂类
public interface Factory {
Product createProdct();
}
//具体工厂类A,负责创建产品A
public class FactoryA implements Factory {
@Override
public Product createProdct() {
return new ProduceA();
}
}
//具体工厂类B,负责创建产品B
public class FactoryB implements Factory {
@Override
public Product createProdct() {
return new ProduceB();
}
}
public class Test {
public static void main(String[] args) {
// 使用具体工厂A创建产品对象
Factory factoryA=new FactoryA();
Product productA=factoryA.createProdct();
productA.operation();
Factory factoryB=new FactoryB();
Product productB=factoryB.createProdct();
productB.operation();
}
}
简单工厂包含四部分:抽象产品类、具体产品类、抽象工厂类、具体工厂类。在简单工厂基础上多了一个抽象工厂类。
- 抽象工厂类: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
- 具体工厂类: 它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
- 抽象产品类: 它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
- 具体产品类: 具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
以上的代码就是遵循工厂模式创建的,工厂方法可以很好的解决开闭原则的问题,但是工厂方法只能创建一种产品,一种产品只能对应一种工厂。因此,当产品过多的时候,也就增加了复杂度,过多的类,也就造成了所谓的“类爆炸”问题。为了解决这个问题,就又出现了抽象工厂模式。
3.3 抽象工厂模式
//抽象产品A
public interface AbstractProductA{
void operationA();
}
//具体产品A1
public ConcreteProductA1 implements AbstractProductA{
public void operationA(){
System.out.println("具体产品A1生产!");
}
}
//具体产品A2
public ConcreteProductA2 implements AbstractProductA{
public void operationA(){
System.out.println("具体产品A2生产!");
}
}
//抽象产品B
public interface AbstractProductB{
void operationB();
}
//具体产品B1
public ConcreteProductB1 implements AbstractProductB{
public void operationB(){
System.out.println("具体产品B1生产!");
}
}
//具体产品B2
public ConcreteProductB2 implements AbstractProductB{
public void operationB(){
System.out.println("具体产品B2生产!");
}
}
//抽象工厂类
public interface AbstractFactory {
AbstractProductA createProdctA();
AbstractProductA createProdctA();
}
//具体工厂类1,负责创建产品1
public class ConcreteFactory1 implements AbstractFactory {
public AbstractProductA createProdctA() {
return new ConcreteProductA1();
}
public AbstractProductB createProdctB() {
return new ConcreteProductB1();
}
}
//具体工厂类2,负责创建产品2
public class ConcreteFactory2 implements AbstractFactory {
public AbstractProductA createProdctA() {
return new ConcreteProductA2();
}
public AbstractProductB createProdctB() {
return new ConcreteProductB2();
}
}
public class Test {
public static void main(String[] args) {
// 使用具体工厂1创建产品对象
AbstractFactory factory1=new ConcreteProductA1();
AbstractProductA productA1=factoryA1.createProdctA();
AbstractProductB productB1=factoryA1.createProdctB();
productA1.operationA();
productB1.operationB();
// 使用具体工厂1创建产品对象
AbstractFactory factory2=new ConcreteProductA1();
AbstractProductA productA2=factoryA2.createProdctA();
AbstractProductB productB2=factoryA2.createProdctB();
productA2.operationA();
productB2.operationB();
}
}
以上代码就是遵循抽象工厂模式创建的,它提供了将相关或依赖对象的创建过程封装起来的方法,通过提供一个工厂接口来封装对象的创建过程,使得具体的工厂类可以动态地切换。抽象工厂模式在工厂方法模式上多了抽象产品分类。相当于简单工厂模式和工厂方法模式的组合模式
- 抽象工厂类: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
- 具体工厂类: 它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
- 抽象产品类: 它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
- 具体产品类: 具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。