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

07GoF之三种工厂模式

GoF(Gang of Four):四人组,《Design Patterns: Elements of Reusable Object-Oriented Software》(《设计模式》)的作者,设计了23种设计模式.但时代发展,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式、MVC模式等)。
● GoF23种设计模式可分为三大类:
○ 创建型(5个):解决对象创建问题。
■ 单例模式
■ 工厂方法模式
■ 抽象工厂模式
■ 建造者模式
■ 原型模式
○ 结构型(7个):一些类或对象组合在一起的经典结构。
■ 代理模式
■ 装饰模式
■ 适配器模式
■ 组合模式
■ 享元模式
■ 外观模式
■ 桥接模式
○ 行为型(11个):解决类或对象之间的交互问题。
■ 策略模式
■ 模板方法模式
■ 责任链模式
■ 观察者模式
■ 迭代子模式
■ 命令模式
■ 备忘录模式
■ 状态模式
■ 访问者模式
■ 中介者模式
■ 解释器模式
● 工厂模式是解决对象创建问题的,所以工厂模式属于创建型设计模式。这里为什么学习工厂模式呢?这是因为Spring框架底层使用了大量的工厂模式。


为什么学工厂模式?
Spring底层就是通过工厂模式+XML+反射机制实现的.


工厂模式的三种形态
**● 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。**一个工厂对应一种产品.
● 第二种:工厂方法模式(Factory Method):是23种设计模式之一。一个工厂对应多种产品.
● 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一。一个工厂对应多种产品系列.


简单工厂模式

Spring中的BeanFactory就使用了简单工厂模式。

简单工厂模式的角色包括三个:
● 工厂类 角色
● 抽象产品 角色
● 具体产品 角色

简单工厂模式的优点
● 客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”。生产和消费分离。

简单工厂模式的缺点
● 缺点1:工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
● 缺点2:不符合OCP开闭原则,在进行系统扩展时,需要修改工厂类。

//抽象产品角色weapon
package com.sunsplanter.factory;
//抽象类无法被创建对象,无法实例化,是用来被子类继承的
//Tank和Weapon是is-a的关系
//且基本功能在不断变化(开炮/投弹),因此用抽象类
public abstract class Weapon {/*** 所有的武器都有攻击行为*/public abstract void attack();
}
//具体产品角色tank/Fighter
package com.sunsplanter.factory;public class Tank extends Weapon{@Overridepublic void attack() {System.out.println("坦克开炮!");}
}```java
package com.sunsplanter.factory;public class Fighter extends Weapon{@Overridepublic void attack() {System.out.println("战斗机投下原子弹!");}
}
//工厂类角色
package com.sunsplanter.factory;public class WeaponFactory {/*** 根据不同的武器类型生产武器* @param weaponType 武器类型* @return 武器对象*/public static Weapon get(String weaponType){if (weaponType == null || weaponType.trim().length() == 0) {return null;}Weapon weapon = null;if ("TANK".equals(weaponType)) {weapon = new Tank();} else if ("FIGHTER".equals(weaponType)) {weapon = new Fighter();}  else {throw new RuntimeException("不支持该武器!");}return weapon;}
}
package com.powernode.factory;public class Client {public static void main(String[] args) {Weapon weapon1 = WeaponFactory.get("TANK");weapon1.attack();Weapon weapon2 = WeaponFactory.get("FIGHTER");weapon2.attack();}
}

工厂方法模式

简单工厂违背了开闭原则,即每次扩展系统时,都要修改工厂类…工厂方法模式的将简单工厂模式的工厂类解耦为抽象工厂+具体工厂,每次扩展系统只要实现一次抽象工厂的接口就可以,不必修改原有程序.

工厂方法模式的角色包括:
● 抽象工厂角色
● 具体工厂角色

● 抽象产品角色
● 具体产品角色

工厂方法模式的优点
● 一个调用者想创建一个对象,只要知道其名称就可以了。
● 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
● 屏蔽产品的具体实现,调用者只关心产品的接口。
工厂方法模式的缺点
● 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

可以看到简单工厂和工厂方法的区别只在于:简单工厂模式的工厂类解耦为抽象工厂+具体工厂,他们的抽象产品角色和具体产品角色仍然是相同的.

//抽象产品角色
package com.sunsplanter.factory;public abstract class Weapon {/*** 所有武器都有攻击行为*/public abstract void attack();
}
//具体产品角色tank/Fighter
package com.sunsplanter.factory;public class Tank extends Weapon{@Overridepublic void attack() {System.out.println("坦克开炮!");}
}```java
package com.sunsplanter.factory;public class Fighter extends Weapon{@Overridepublic void attack() {System.out.println("战斗机投下原子弹!");}
}
//抽象工厂角色(武器工厂接口)
package com.sunsplanter.factory;public interface WeaponFactory {Weapon get();
}
//具体工厂角色
package com.sunsplanter.factory;public class TankFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Tank();}
}
//具体工厂角色
package com.sunsplanter.factory;public class FighterFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Fighter();}
}
package com.sunsplanter;public class Client {public static void main(String[] args) {TankFactory tankFactory = new TankFactory();//Weapon类型的gunTank tank = tankFactory.get();tank.attack();}
}

如果想扩展一个新的产品,只要新增一个产品类,再新增一个该产品对应的工厂即可,例如新增:匕首

//新增一个具体产品角色
package com.sunsplanter;public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("砍丫的!");}
}
//新增一个具体工厂角色
package com.sunsplanter;public class DaggerFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Dagger();}
}

抽象工厂模式

在工厂方法模式上再次进化,允许存在多个产品系列/工厂系列.

http://www.lryc.cn/news/278895.html

相关文章:

  • JAVA面试部分——后端-线程前篇
  • 【小沐学C++】C++ 实现鼠标键盘钩子HOOK
  • 【pycharm】常见问题与解决
  • flask web学习之表单(一)
  • @ControllerAdvice 使用场景
  • 二极管选型怎么选?常用参数要熟练~
  • 【小白专用】C#关于角色权限系统
  • 代码随想录算法训练营
  • 统计学-R语言-3
  • spring动态控制定时任务
  • 3. Mybatis 中SQL 执行原理
  • 第一次在RUST官方论坛上留言发布我的Rust板箱
  • LabVIEW 智能化矿用定向钻机液压系统监测
  • GO数据库操作
  • PyTorch简单理解ChannelShuffle与数据并行技术解析
  • MySQL 8查询语句之查询所有字段、特定字段、去除重复字段、Where判断条件
  • LLaMA-Factory添加adalora
  • 多端多用户万能DIY商城系统源码:自营+多商户入驻商城系统 独立部署 带完整的安装代码包以及搭建教程
  • Qt 6之七:学习资源
  • 解决大模型的幻觉问题:一种全新的视角
  • mysql进阶-重构表
  • Element-ui图片懒加载
  • Linux系统——DNS解析详解
  • 初识Ubuntu
  • Casper Network (CSPR)2024 年愿景:通过投资促进增长
  • 《MySQL系列-InnoDB引擎06》MySQL锁介绍
  • 获取多个PDF文件的内容并保存到excel上
  • 深入了解网络流量清洗--使用免费的雷池社区版进行防护
  • 【FFMPEG应用篇】基于FFmpeg的转码应用(FLV MP4)
  • LInux初学之路linux的磁盘分区/远程控制/以及关闭图形界面/查看个人身份