文章目录
工厂模式
工厂模式(Factory Pattern),是Java中创建型的模式之一,它提供了一个创建对象的方式(使用工厂创建),将创造对象的过程和使用对象的过程分离。
举个例子,比如之前人们需要使用一个圆形的木板,就需要去拿到创造圆形木板的细节,使用工具去创造一个圆形木板出一个圆形木板,然后去使用这个木板。
现在我们使用工厂来创造实例的话,就像是我们现在需要一个圆形木板,只需要将我们的要求和具体要求告诉工厂,由工厂来创建这个木板,我们就只需要等待使用就好了。这样我们就完成了创建对象和适用对象的过程分离,通过使用工厂模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。
在Java的工厂模式中有三个工厂类型,其中工厂方法模式和抽象工厂模式属于Java的23中设计模式。
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
简单工厂模式
1.什么是简单工厂模式?
简单工厂模式,又叫做静态工厂模式(Static Factory Method),由一个工厂对象决定创建出哪一种产品类的实例,传递一个参数进入静态工厂类,然后根据参数动态决定应该创建哪一个产品类。简单工厂模式是另外两种工厂的基础,通过了解简单工厂模式可以让我们对另外两种设计思路有更深入的理解和掌握
2.简单工厂优缺点
优点:
在使用的时候很符合封装的特点,只需要传入一个正确的参数,就可以获取所需类型对象。
降低了客户端和产品类之间的耦合
缺点:
维护升级不太方便,简单工厂内部的逻辑太过繁杂,比如在工厂中新增产品时,需要修改工厂类的判断逻辑不符合开闭原则(OCP,模块和函数应该对拓展开放,对修改关闭)。
3.简单工厂类的实现
创建一个Shape的接口
public interface Shape {
void getMessage();
}
创建Shape的实现类
public class Circle implements Shape{
@Override
public void getMessage() {
System.out.println("我是一个圆圆形");
}
}
public class Rectangle implements Shape{
@Override
public void getMessage() {
System.out.println("我是一个矩形");
}
}
public class Squere implements Shape{
@Override
public void getMessage() {
System.out.println("我是一个正方形");
}
}
创建Shape的工厂类ShapeFactory
public class ShapeFactory {
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("circle")){
return new Circle();
}else if(shapeType.equalsIgnoreCase("rectangle")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("squere")){
return new Squere();
}
return null;
}
public Shape getShape(Class clazz) throws Exception{
return (Shape) clazz.newInstance();
}
}
测试方法
public static void main(String[] args) throws Exception {
ShapeFactory shapeFactory = new ShapeFactory();
Shape circle = shapeFactory.getShape("Circle");
circle.getMessage();
Shape circle0 = shapeFactory.getShape(circle.getClass());
circle0.getMessage();
}
工厂方法模式
1.什么是工厂方法模式
工厂方法模式是对简单工厂模式的进一步抽象化。简单工厂的对象创建是在工厂类中实现的,而工厂方法模式将对象的创建延迟到子类中进行,从而实现了更好的扩展性,维护起来会更方便。在工厂方法模式中,抽象工厂类负责定义创建产品对象的接口,而具体工厂子类负责对象的创建。
工厂类和其子类可以理解成一个总工厂,和下属的分工厂的关系,当然这个总工厂只负责下发业务,而具体的产品生产则有分工厂(子类)负责,每个子类负责生产不同类型的产品(实例对象)。
2.工厂方法模式的优缺点
优点
- 在维护工厂类的方法,比如增加新的产品进工厂时不需要改变总工厂,只需要开设新的子工厂就可以了(符合开闭原则)
- 将产品和类和客户端之间通过抽象产品和抽象工厂隔绝,不需要使用具体的初始化产品
缺点
增加了更多的类,项目结构更加复杂
3.工厂方法的实现
电子产品的接口
public interface Electronics {
void use();
}
产品的实现类
Keypan键盘类
public class Keypan implements Electronics{
@Override
public void use() {
System.out.println("键盘能打字");
}
}
Mouse鼠标类
public class Mouse implements Electronics{
@Override
public void use() {
System.out.println("鼠标在发光");
}
}
抽象的工厂类
public abstract class Creator {
public abstract Electronics factoryMethod();
// 一个通用的方法,使用工厂方法来创建产品
public final Electronics createProduct() {
Electronics electronic = factoryMethod();
// 这里可以添加一些额外的逻辑,比如初始化产品等
return electronic;
}
}
工厂类的实现子类
KeypanFactory键盘工厂类
public class KeypanFactory extends Creator{
@Override
public Electronics factoryMethod() {
return new Keypan();
}
}
MouseFactory鼠标工厂类
public class MouseFactory extends Creator{
@Override
public Electronics factoryMethod() {
return new Mouse();
}
}
客户端代码
public class Test {
public static void main(String[] args) {
Creator mouseFactory = new MouseFactory();
Electronics mouse = mouseFactory.createProduct();
mouse.use();
}
}
输出结果
鼠标在发光
在工厂方法模式中新增U盘产品
要想在工厂方法模式中新增产品,需要新增两个类
1.第一个U盘产品类
public class Upan implements Electronics{
@Override
public void use() {
System.out.println("U盘可以存储文件");
}
}
2.第二个U盘工厂子类
public class UpanFactory extends Creator{
@Override
public Electronics factoryMethod() {
return new Upan();
}
}
这种方式维护起来不需要更改代码,只需要扩展出新的类就可以了,代码维护起来更加容易。
抽象工厂模式
1.什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个其他工厂的工厂(超级工厂接口),它提供了一种创建对象的最佳方式。在抽象工厂模式中,超级工厂接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都生产需要的对象。
抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
2.应用实例
客户只知道创建产品的工厂名,“海尔"和"海信”,这两家工厂都可以生成一整套的家电,比如冰箱和电视,而不知道具体的产品名,就可以创建一整套的海尔(或海信)的家电。创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。客户不关心创建产品的细节,只关心产品的品牌。
3.抽象工厂模式的四类结构
-
抽象工厂(Abstract Factory):
- 声明了一组用于创建产品对象的方法,每个方法对应一组产品类型(生产冰箱,生产电视)。
- 抽象工厂可以是接口或抽象类。
-
具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例(比如海尔工厂负责生产海尔冰箱,生产海尔电视)。
-
抽象产品(Abstract Product):
- 定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法(比如电视开机,电视关机)。
- 抽象产品类可能有多个(比如冰箱抽象类,电视抽象类)
-
具体产品(Concrete Product):
- 实现了抽象产品接口,定义了具体产品的特定行为和属性。
- 比如海尔冰箱的各种功能。
4.抽象工厂模型的实现
(1)抽象工厂
//抽象产品工厂(定义了同一个产品族的产品生产行为)
public interface IProductFactory {
//生产手机
IPhone produceTelPhone();
//生产路由器
IRouter produceRouter();
}
(2)具体工厂
华为产品工厂
/**
* 华为产品工厂
*/
public class HuaweiProductFactory implements IProductFactory {
@Override
public IPhone produceTelPhone() {
System.out.println(">>>>>>生产华为手机");
return new HuaweiPhone();
}
@Override
public IRouter produceRouter() {
System.out.println(">>>>>>生产华为路由器");
return new HuaweiRouter();
}
}
小米产品工厂
/**
* 小米产品工厂
*/
public class XiaomiProductFactory implements IProductFactory {
@Override
public IPhone produceTelPhone() {
System.out.println(">>>>>>生产小米手机");
return new XiaomiPhone();
}
@Override
public IRouter produceRouter() {
System.out.println(">>>>>>生产小米路由器");
return new XiaomiRouter();
}
}
(3)抽象产品
抽象手机
/**
* 手机产品接口
*/
public interface IPhone {
//开机
void start();
//关机
void shutdown();
//打电话
void callUp();
//发送消息
void sendSMS();
}
抽像路由器
/**
* 路由器产品接口
*/
public interface IRouter {
//开机
void start();
//关机
void shutdown();
//开启wifi
void openWifi();
//设置参数
void setting();
}
(4)具体产品
华为手机
/**
* 华为手机产品
*/
public class HuaweiPhone implements IPhone {
@Override
public void start() {
System.out.println("开启华为手机");
}
@Override
public void shutdown() {
System.out.println("关闭华为手机");
}
@Override
public void callUp() {
System.out.println("用华为手机打电话");
}
@Override
public void sendSMS() {
System.out.println("用华为手机发短信");
}
}
华为路由器
/**
* 华为路由器产品
*/
public class HuaweiRouter implements IRouter {
@Override
public void start() {
System.out.println("启动华为路由器");
}
@Override
public void shutdown() {
System.out.println("关闭华为路由器");
}
@Override
public void openWifi() {
System.out.println("打开华为路由器的wifi功能");
}
@Override
public void setting() {
System.out.println("设置华为路由器参数");
}
}
小米手机
/**
* 小米手机产品
*/
public class XiaomiPhone implements IPhone {
@Override
public void start() {
System.out.println("开启小米手机");
}
@Override
public void shutdown() {
System.out.println("关闭小米手机");
}
@Override
public void callUp() {
System.out.println("用小米手机打电话");
}
@Override
public void sendSMS() {
System.out.println("用小米手机发短信");
}
}
小米路由器
/**
* 小米路由器产品
*/
public class XiaomiRouter implements IRouter {
@Override
public void start() {
System.out.println("启动小米路由器");
}
@Override
public void shutdown() {
System.out.println("关闭小米路由器");
}
@Override
public void openWifi() {
System.out.println("打开小米路由器的wifi功能");
}
@Override
public void setting() {
System.out.println("设置小米路由器参数");
}
}
(5)客户端
public class Test {
public static void main(String[] args) {
System.out.println("===================小米系列产品=================");
//小米产品工厂实例
IProductFactory xiaomiProductFactory = new XiaomiProductFactory();
//生产小米路由器
IRouter xiaomiRouter = xiaomiProductFactory.produceRouter();
xiaomiRouter.start();
xiaomiRouter.setting();
xiaomiRouter.openWifi();
xiaomiRouter.shutdown();
//生产小米手机
IPhone xiaomiPhone = xiaomiProductFactory.produceTelPhone();
xiaomiPhone.start();
xiaomiPhone.callUp();
xiaomiPhone.sendSMS();
xiaomiPhone.shutdown();
System.out.println("===================华为系列产品=================");
//华为产品工厂实例
IProductFactory huaweiProductFactory = new HuaweiProductFactory();
//生产华为路由器
IRouter huaweiRouter = huaweiProductFactory.produceRouter();
huaweiRouter.start();
huaweiRouter.setting();
huaweiRouter.openWifi();
huaweiRouter.shutdown();
//生产华为手机
IPhone huaweiPhone = huaweiProductFactory.produceTelPhone();
huaweiPhone.start();
huaweiPhone.callUp();
huaweiPhone.sendSMS();
huaweiPhone.shutdown();
}
}
输出结果
===================小米系列产品================= >>>>>>生产小米路由器 启动小米路由器 设置小米路由器参数 打开小米路由器的wifi功能 关闭小米路由器 生产小米手机 开启小米手机 用小米手机打电话 用小米手机发短信 关闭小米手机 ===================华为系列产品================= 生产华为路由器 启动华为路由器 设置华为路由器参数 打开华为路由器的wifi功能 关闭华为路由器 生产华为手机 开启华为手机 用华为手机打电话 用华为手机发短信 关闭华为手机