1.概念
简单工厂模式是一种创建型设计模式(什么是创建型模式,见我发布的单例模式详解文章,或者狗子们自己百度下),它提供了一种创建对象的方式,而无需暴露对象的创建逻辑。在简单工厂模式中,通过一个工厂类来创建对象,客户端只需要提供所需对象的类型,而不需要关心具体的创建过程。
简单来说就是根据传入的参数返回对应的对象。
这种方式在一些框架中很常见,当我们自己需要扩展的时候就可以继承框架的一些类,比如Spring里面。
你如果觉得下面关于abstract的知识点复习(本模式会用到该关键字)介绍很繁琐,就看这段就行了。
为什么会有抽象类,如果两子类去继承父类,是因为需要一些公用的属性和方法,但是父类的一些方法并不知道要干什么,这个时候就可以使用抽象了,父类并不具体干什么,子类可以自己干,但是必须干。上面的简单工厂模式就是这样的,我知道你们都要造产品,但是各自具体怎么造就看自己了。接口是强制规范,非通用属性,这种就是设计思想上的区别。
2.要素
- 工厂类(Factory):负责创建对象的类,它通常包含一个创建对象的方法,根据客户端提供的参数来创建具体的对象。
- 抽象产品类(Product):定义了产品的共同属性和方法,它可以是接口或抽象类。
- 具体产品类(ConcreteProduct):实现了抽象产品类定义的方法,是工厂类创建的目标对象。
3.优势和劣势
简单工厂模式的优点是将对象的创建和使用分离,客户端只需要关心所需对象的类型,而不需要关心具体的创建过程。同时,通过工厂类的静态方法来创建对象,可以避免直接使用new关键字创建对象,降低了耦合性。
然而,简单工厂模式的缺点是当需要添加新的产品时,需要修改工厂类的代码,违反了开闭原则(面向对象设计的一种原则,要求新的需求不能修改已有的代码,尽量通过继承或者实现接口)。同时,工厂类负责创建所有的产品对象,当产品种类较多时,工厂类的代码会变得复杂。
4.创建步骤和案例
abstract关键字在本文后面给狗子们复习下。
//首先定义一个抽象产品类
public abstract class Product {
public abstract void show();
}
/**
*我们定义两个具体产品类(ConcreteProductA和ConcreteProductB),它们分别实现了抽象产品类的show方法:
**/
public class ConcreteProductA extends Product {
@Override
public void show() {
System.out.println("A");
}
}
public class ConcreteProductB extends Product {
@Override
public void show() {
System.out.println("B");
}
}
/**
*我们定义一个工厂类(Factory),它包含一个静态方法用于创建产品对象。根据客户端提供的参数,工厂类
*决定创建哪个具体产品对象:
**/
public class Factory {
public static Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
} else {
throw new IllegalArgumentException("Invalid product type");
}
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
Product productA = Factory.createProduct("A");
productA.show(); // 输出:A
Product productB = Factory.createProduct("B");
productB.show(); // 输出:B
}
}
客户端通过调用工厂类的静态方法createProduct来创建具体的产品对象。客户端只需要提供产品的类型("A"或"B"),而不需要关心具体的创建过程。工厂类根据客户端提供的参数来决定创建哪个具体产品对象,并返回给客户端使用。
这样,简单工厂模式实现了对象的创建和使用的分离,客户端只需要关心产品的类型,而不需要关心具体的创建过程。同时,通过工厂类来创建对象,可以避免直接使用new关键字创建对象,降低了耦合性。
5.知识点复习
5.1 abstract
5.1.1 作用
用于定义抽象类和抽象方法
- 抽象类是一种不能被实例化的类,它只能被继承。
- 抽象类可以包含抽象方法和非抽象方法。
- 抽象方法是一种没有实现体的方法,它只有方法的声明,没有方法体。
- 子类继承抽象类后,必须实现抽象方法。
抽象类的主要作用是为了提供一种模板或者规范,让子类去实现具体的功能。抽象类可以包含一些通用的方法和属性,子类可以继承这些方法和属性,并根据自己的需求进行具体的实现。
5.1.2 定义
抽象类的定义: abstract class ClassName { // 抽象类的成员变量和非抽象方法 }
抽象方法的定义: abstract returnType methodName(parameters);
需要注意的是,抽象类可以有构造方法,但是不能被实例化。只有具体的子类才能被实例化,所以抽象类不能被实例化,只能被继承,子类必须实现抽象方法。抽象类的主要作用是提供一种模板或者规范,让子类去实现具体的功能。
5.1.3 和接口的区别
抽象类和接口是Java中两种不同的机制,用于实现类的继承和多态性。
抽象类:
- 抽象类是一种不能被实例化的类,只能被继承。
- 抽象类可以包含抽象方法和非抽象方法。
- 抽象方法是一种没有实现体的方法,只有方法的声明,没有方法体。
- 子类继承抽象类后,必须实现抽象方法。
- 抽象类可以有构造方法,但是不能被实例化。
- 抽象类可以包含成员变量和非抽象方法的实现。
接口:
- 接口是一种完全抽象的类,它只包含抽象方法和常量。
- 接口中的方法都是抽象方法,没有方法体。
- 类可以实现多个接口,但是只能继承一个类。
- 实现接口的类必须实现接口中的所有方法。
- 接口中的常量默认是public static final的,可以直接通过接口名访问。
- 接口可以被其他接口继承,形成接口的继承关系。
5.1.4抽象类和接口的选择
- 如果需要定义一些通用的方法和属性,并且希望子类进行具体的实现,可以使用抽象类。
- 如果需要定义一些规范或者契约,并且希望多个类去实现这些规范,可以使用接口。
- 如果一个类需要继承其他类的同时实现多个接口,可以使用抽象类来继承其他类,再实现接口。
总结一下,抽象类和接口是Java中实现继承和多态性的两种机制。抽象类是一种不能被实例化的类,可以包含抽象方法和非抽象方法;接口是一种完全抽象的类,只包含抽象方法和常量。抽象类适用于定义通用的方法和属性,接口适用于定义规范和契约。