Python 官方文档:入门教程 => 点击学习
目录工厂模式1.简单工厂1.1结构1.2实现1.3优缺点1.4扩展2.工厂方法2.1结构2.2实现2.3优缺点3.抽象工厂3.1结构3.2实现3.3优缺点4.模式扩展4.1实现工厂模
在Java应用程序中对象无处不在,这些对象都需要进行创建,如果创建的时候直接new对象,那么如果我们要更换对象,所有new对象的地方都需要进行更改。违背了软件设计原则中的开闭原则。如果我们使用工厂生产对象,只需要在工厂中关注对象的改变即可,达到了与对象解耦的目的,工厂模式最大的特点就是解耦合
补充:
开闭原则: 对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。是为了使程序的扩展性好,易于维护和升级。
以点咖啡为例:
咖啡抽象类
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{
@Override
public String getName(){
return "美式咖啡";
}
}
拿铁咖啡类
public class LatteCoffee extends Coffee {
@Override
public String getName(){
return "拿铁咖啡";
}
}
咖啡工厂类
public class CoffeeFactory {
public Coffee createCoffee(String type){
Coffee coffee = null;
if("american".equals(type)){
coffee = new AmericanCoffee();
}else if("latten".equals(type)){
coffee = new LatteCoffee();
}else{
throw new RuntimeException("没有此类型的咖啡");
}
return coffee;
}
}
咖啡店类
public class CoffeeStore {
public Coffee orderCoffee(String type){
CoffeeFactory factory = new CoffeeFactory();
//调用生产咖啡的方法
Coffee coffee = factory.createCoffee(type);
coffee.addMilk();
coffee.addSugar();
return coffee;
}
}
测试类
public class Test {
public static void main(String[] args) {
CoffeeStore coffeeStore = new CoffeeStore();
Coffee coffee = coffeeStore.orderCoffee("latten");
System.out.println(coffee.getName());
}
}
类图
咖啡工厂负责生产咖啡(具体工厂),咖啡店通过咖啡工厂选取咖啡
其实简单工厂是大家在实际写代码的时候经常用到的,虽然简单工厂实现了咖啡店与咖啡的耦合,但是可以明显看到咖啡与咖啡工厂又耦合起来了,后期如果增加咖啡的新品种,我们需要修改咖啡工厂的代码,这又违背了“开闭原则”。
注意:
简单工厂和不使用工厂是有很大区别的,如果咖啡店有多个,不使用工厂如果遇到新增咖啡需要修改所有咖啡店,但是使用工厂只需要修改咖啡工厂,类似于将所有咖啡店抽取出一个抽象的咖啡店。
优点:
封装了创建对象的过程,可以通过参数直接获取对象,把对象的创建和业务逻辑层分开,这样可以避免之后修改客户代码,如果需要实现新产品直接修改工厂类,更容易扩展。
缺点:
增加新产品时还需要修改工厂类的代码,违背了“开闭原则”。
静态工厂,将工厂类中创建对象的功能定义为静态的,这样不需要再创建工厂类,直接通过类名调用静态方法,类似于工具类
public class CoffeeFactory {
//静态方法
public static Coffee createCoffee(String type){
Coffee coffee = null;
if("american".equals(type)){
coffee = new AmericanCoffee();
}else if("latten".equals(type)){
coffee = new LatteCoffee();
}else{
throw new RuntimeException("没有此类型的咖啡");
}
return coffee;
}
}
对工厂进行抽象,每一种产品对应一个具体工厂,新增产品只需要再新增对应的具体工厂,符合”开闭原则“
抽象咖啡类和具体咖啡类不变
咖啡工厂(抽象工厂)
public interface CoffeeFactory {
Coffee createCoffee();
}
美式咖啡工厂(具体工厂)
public class AmericanCoffeeFactory implements CoffeeFactory{
//美式咖啡工厂对象,专门生产美式咖啡
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
拿铁咖啡工厂(具体工厂)
public class LatteCoffeeFactory implements CoffeeFactory{
//拿铁咖啡工厂对象,专门生产拿铁咖啡
@Override
public 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.addSugar();
coffee.addMilk();
return coffee;
}
}
测试类
public class Test {
public static void main(String[] args) {
//创建咖啡店对象
CoffeeStore coffeeStore = new CoffeeStore();
//创建工厂对象
CoffeeFactory factory = new AmericanCoffeeFactory();
coffeeStore.setFactory(factory);
//点咖啡
Coffee coffee = coffeeStore.orderCoffee();
System.out.println(coffee.getName());
}
}
类图
我们只需要知道所点咖啡具体对应的工厂对象,通过咖啡店调用对应的工厂,由工厂创建咖啡对象实现点咖啡的过程
优点:
缺点:
每增加一个产品就要增加一个对应的具体工厂类,增加的系统的复杂性。如果具体产品种类过多,那么大量的工厂类不仅难以管理,而且也会造成程序中创建的对象过多,严重影响内存性能
咖啡抽象类
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{
@Override
public String getName(){
return "美式咖啡";
}
}
拿铁咖啡类
public class LatteCoffee extends Coffee {
@Override
public String getName(){
return "拿铁咖啡";
}
}
甜品抽象类
public abstract class Dessert {
//甜品抽象类
public abstract void show();
}
抹茶慕斯类
public class MatchaMousse extends Dessert{
//抹茶慕斯类
@Override
public void show() {
System.out.println("抹茶慕斯");
}
}
提拉米苏类
public class Tiramisu extends Dessert{
//提拉米苏类
@Override
public void show() {
System.out.println("提拉米苏");
}
}
甜品工厂
public interface DessertFactory {
Coffee createCoffee();
Dessert createDessert();
}
美式风味甜品工厂类
public class AmericanDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
@Override
public Dessert createDessert() {
return new MatchaMousse();
}
}
意大利风味甜品工厂类
public class ItalyDessertFactory implements DessertFactory {
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
@Override
public Dessert createDessert() {
return new Tiramisu();
}
}
测试类
public class Test {
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();
}
}
类图
由类图可见,抽象工厂不再是一个具体工厂对应一个产品,而是一个具体工厂对应一个产品族。如果需要增加一个产品族只需加对应的工厂类,符合”开闭原则“
优点:
在工厂方法的基础上减少了部分对象的创建,适合于每次只使用同一产品族的对象这类应用场景
缺点:
当产品族中需要增加一个产品时,所有工厂都要修改
配置文件+简单工厂
通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件的全类名,通过反射创建对象并存储在容器中,如果需要直接从容器中获取(spring ioc原理)
1.定义配置文件
american = com.xue.config_factory.AmericanCoffee
latten = com.xue.config_factory.LatteCoffee
2.改进工厂类
public class CoffeeFactory {
//1.定义容器对象存储咖啡对象
private static HashMap<String, Coffee> map = new HashMap<>();
//2.加载配置文件
static {
//创建 Properties对象
Properties properties = new Properties();
//调用properties对象中的load方法进行配置文件的加载
InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(is);
//从properties中获取全类名
Set<Object> keys = properties.keySet();
for (Object key : keys) {
String className = properties.getProperty((String) key);
//通过反射创建对象
Class class1 = Class.forName(className);
Coffee coffee = (Coffee) class1.newInstance();
//将名称和对象存储在容器中
map.put((String) key,coffee);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据名称获取对象
public static Coffee createCoffee(String name) {
return map.get(name);
}
}
静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件和创建对象写在静态代码块中只需要执行一次
测试类
public class Test {
public static void main(String[] args) {
Coffee coffee = CoffeeFactory.createCoffee("american");
System.out.println(coffee.getName());
System.out.println("------------");
Coffee latten = CoffeeFactory.createCoffee("latten");
System.out.println(latten.getName());
}
}
成功!!!
以上就是Java设计模式——工厂模式的介绍及四种实现方式 往期链接:单例模式
到此这篇关于Java超详细讲解设计模式之一的工厂模式的文章就介绍到这了,更多相关Java 工厂模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Java超详细讲解设计模式之一的工厂模式
本文链接: https://lsjlt.com/news/144013.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0