当前位置: 首页 > ds >正文

工厂设计模式

简单工厂模式

  简单工厂不是一种设计模式,反而比较像是一种编程习惯。
结构

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

实现
在这里插入图片描述

public abstract class Coffee {public abstract String getName();//加糖public void addSugar() {System.out.println("加糖");}//加奶public void addMilk() {System.out.println("加奶");}
}
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}
public class SimpleCoffeeFactory {public Coffee createCoffee(String type) {//根据不同的类型创建不同的咖啡对象Coffee coffee = null;if ("american".equals(type)) {coffee = new AmericanCoffee();} else if ("latte".equals(type)) {coffee = new LatteCoffee();} else {throw new RuntimeException("对不起,您所点的咖啡没有");}return coffee;}
}
public class CoffeeStore {public Coffee orderCoffee(String type) {//创建一个简单工厂对象SimpleCoffeeFactory simpleCoffeeFactory = new SimpleCoffeeFactory();//根据用户需求获取咖啡对象Coffee coffee = simpleCoffeeFactory.createCoffee(type);//加配料coffee.addMilk();coffee.addSugar();return coffee;}
}
public class Client {public static void main(String[] args) {//创建咖啡店对象CoffeeStore coffeeStore = new CoffeeStore();//点咖啡Coffee coffee = coffeeStore.orderCoffee("american");System.out.println(coffee.getName());}
}

优缺点

优点:封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

静态工厂
  在开发中也有一部分人将工厂类中的创建对象的功能定义为静态的,这个就是静态工厂模式,它也不是23种设计模式中的。

public class SimpleCoffeeFactory {public static Coffee createCoffee(String type) {//根据不同的类型创建不同的咖啡对象Coffee coffee = null;if ("american".equals(type)) {coffee = new AmericanCoffee();} else if ("latte".equals(type)) {coffee = new LatteCoffee();} else {throw new RuntimeException("对不起,您所点的咖啡没有");}return coffee;}
}
public class CoffeeStore {public Coffee orderCoffee(String type) {Coffee coffee = SimpleCoffeeFactory.createCoffee(type);//加配料coffee.addMilk();coffee.addSugar();return coffee;}
}

工厂方法模式

概念
  定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一产品类的实例化延迟到其工厂的子类。

结构

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

实现
在这里插入图片描述

public abstract class Coffee {public abstract String getName();//加糖public void addSugar() {System.out.println("加糖");}//加奶public void addMilk() {System.out.println("加奶");}
}
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}
public interface CoffeeFactory {//创建咖啡对象的方法Coffee createCoffee();
}
public class AmericanCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}
}
public class LatteCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new LatteCoffee();}
}
public class CoffeeStore {private CoffeeFactory factory;public void setFactory(CoffeeFactory factory) {this.factory = factory;}//点咖啡的方法public Coffee orderCoffee(){Coffee coffee = factory.createCoffee();coffee.addMilk();coffee.addSugar();return coffee;}
}
public class Client {public static void main(String[] args) {//创建咖啡店对象CoffeeStore coffeeStore = new CoffeeStore();//创建咖啡工厂对象CoffeeFactory factory = new LatteCoffeeFactory();//CoffeeFactory factory = new AmericanCoffeeFactory();coffeeStore.setFactory(factory);Coffee coffee = coffeeStore.orderCoffee();System.out.println(coffee.getName());}
}

优缺点

优点:用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

抽象工厂模式

概念
  一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

结构

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

实现
在这里插入图片描述

public abstract class Coffee {public abstract String getName();//加糖public void addSugar() {System.out.println("加糖");}//加奶public void addMilk() {System.out.println("加奶");}
}
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}
public abstract class Dessert {public abstract void show();
}
public class Trimisu extends Dessert {@Overridepublic void show() {System.out.println("提拉米苏");}
}
public class MatchaMousse extends Dessert {@Overridepublic void show() {System.out.println("抹茶慕斯");}
}
public interface DessertFactory {//生产咖啡的功能Coffee createCoffee();//生产甜品的功能Dessert createDessert();
}
public class AmericanDessertFactory implements DessertFactory {@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}@Overridepublic Dessert createDessert() {return new MatchaMousse();}
}
public class ItalyDessertFactory implements DessertFactory {@Overridepublic Coffee createCoffee() {return new LatteCoffee();}@Overridepublic Dessert createDessert() {return new Trimisu();}
}
public class Client {public static void main(String[] args) {//创建工厂对象//ItalyDessertFactory factory = new ItalyDessertFactory();AmericanDessertFactory factory = new AmericanDessertFactory();//通过工厂对象创建产品对象Coffee coffee = factory.createCoffee();Dessert dessert = factory.createDessert();System.out.println(coffee.getName());dessert.show();}
}

优缺点

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

使用场景

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

模式扩展

简单工厂+配置文件解除耦合

american=pattern.factory.config_factory.AmericanCoffee
latte=pattern.factory.config_factory.LatteCoffee
public abstract class Coffee {public abstract String getName();//加糖public void addSugar() {System.out.println("加糖");}//加奶public void addMilk() {System.out.println("加奶");}
}
public class AmericanCoffee extends Coffee {@Overridepublic String getName() {return "美式咖啡";}
}
public class LatteCoffee extends Coffee {@Overridepublic String getName() {return "拿铁咖啡";}
}
public class CoffeeFactory {//加载配置文件,获取配置文件中的全类名,并创建该类的对象进行存储。//1.定义容器对象存储咖啡对象。private static HashMap<String, Coffee> map = new HashMap<>();//2.加载配置文件,一次性创建好对象。static {//创建Properties对象Properties p = new Properties();//获取配置文件的流对象InputStream inputStream = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");//加载配置文件try {p.load(inputStream);//从p集合中获取全类名并创建对象Set<Object> keys = p.keySet();for (Object key : keys) {//获取全类名String className = p.getProperty((String) key);//通过反射技术创建对象Class clazz = Class.forName(className);Coffee coffee = (Coffee) clazz.newInstance();//将名称和对象存储到容器中map.put((String) key, coffee);}} catch (Exception e) {throw new RuntimeException(e);}}//根据名称获取对象public static Coffee createCoffee(String name) {return map.get(name);}
}
public class Client {public static void main(String[] args) {Coffee coffee = CoffeeFactory.createCoffee("american");System.out.println(coffee.getName());System.out.println("====================");Coffee coffee1 = CoffeeFactory.createCoffee("latte");System.out.println(coffee1.getName());}
}

  静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件以及创建对象写在静态代码块中,目的就是只需要执行一次。

实例

public class Demo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("令狐冲");list.add("风清扬");list.add("任我行"); //获取迭代器对象Iterator<String> it = list.iterator(); //使用迭代器遍历while (it.hasNext()) {String ele = it.next();System.out.println(ele);}}
}

  使用迭代器遍历集合,获取集合中的元素。而单列集合获取迭代器的方法就使用到了工厂方法模式。
在这里插入图片描述
  Collection接口是抽象工厂类,ArrayList是具体的工厂类;Iterator接口是抽象商品类,ArrayList类中的Iter内部类是具体的商品类。在具体的工厂类中iterator()方法创建具体的商品类的对象。

1,DateForamt类中的getInstance()方法使用的是工厂模式;
2,Calendar类中的getInstance()方法使用的是工厂模式;

http://www.xdnf.cn/news/2884.html

相关文章:

  • GRPO vs SFT:强化学习提升大模型多模态推理泛化能力的原因研究
  • 2.2.1goweb内置的 HTTP 处理程序
  • Daytona - 开源开发环境管理器
  • 【前端】CSS实现div双背景图叠加
  • QTableView复选框居中
  • Java多线程入门案例详解:继承Thread类实现线程
  • 将本地Springboot项目部署到Linux服务器
  • Web开发之三层架构
  • 从困局到破局的AI+数据分析
  • vscode以管理员身份运行报错
  • 用 Python打造交互式图片-音视频管理器:代码分析与实践
  • 厚铜pcb生产厂家哪家好?
  • 深入解析C2服务器:网络攻击的核心枢纽
  • 莫队算法学习笔记
  • Spring-全面详解(学习总结)
  • 具身智能机器人的应用场景及最新进展
  • Java写项目前的准备工作指南(技术栈选择 环境搭建和工具配置 项目结构设计与模块划分)
  • springboot 视频分段加载在线播放
  • 【含文档+PPT+源码】基于微信小程序的旅游论坛系统的设计与实现
  • Linux中的计划任务
  • Python----卷积神经网络(卷积为什么能识别图像)
  • 顶会idea:Mamba+CNN暴力涨点新突破!
  • vue复习91~135
  • Blender插件 幽灵拖尾特效动画 Ghosts V1.0
  • 重测序关系矩阵构建方式汇总
  • 什么是SCADA系统?
  • Redis ⑦-set | Zset
  • [OS] POSIX C库介绍
  • pgrep和pkill命令详解
  • Dockerfile讲解与示例汇总