工厂模式
工厂模式的三种形态: 工厂模式是解决对象创建问题的属于创建型设计模式,Spring框架底层使用了大量的工厂模式
- 第一种:简单工厂模式是工厂方法模式的一种特殊实现,简单工厂模式又叫静态工厂方法模式不属于23种设计模式之一
- 第二种:工厂方法模式, 是23种设计模式之一
- 第三种:抽象工厂模式, 是23种设计模式之一
简单/静态工厂模式
简单工厂模式的优点
- 客户端程序不需要关心对象的创建细节,需要哪个对象时只需要向工厂索要即可, 客户端只负责
消费
,工厂只负责生产
, 初步实现了责任的分离
简单工厂模式的缺点
- 工厂类集中了所有产品的创造逻辑,有人把它叫做
上帝类/全能类
, 显然工厂类非常关键一旦出问题整个系统将瘫痪 - 不符合OCP开闭原则,在进行系统产品扩展时需要修改工厂类的代码创建新的产品,这样客户端才能获取到扩展的产品
简单工厂模式的角色包括三个:抽象产品角色
,具体产品角色
, (静态)工厂类角色(
提供创建对象的静态方法)
// 抽象产品角色: 武器
public abstract class Weapon {
// 所有的武器都有攻击行为
public abstract void attack();
}
// 具体产品角色:坦克
public class Tank extends Weapon{
@Override
public void attack() {
System.out.println("坦克开炮!");
}
}
// 具体产品角色:战斗机
public class Fighter extends Weapon{
@Override
public void attack() {
System.out.println("战斗机投下原子弹!");
}
}
//工厂类角色:根据不同的武器类型不同的生产武器
public class WeaponFactory {
// 根据不同的武器类型生产不同的武器
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;
}
}
编写测试程序,通过指定武器的类型从静态工厂中获取对应的武器
public class Client {
public static void main(String[] args) {
Weapon weapon1 = WeaponFactory.get("TANK");
weapon1.attack();
Weapon weapon2 = WeaponFactory.get("FIGHTER");
weapon2.attack();
}
}
工厂方法模式
工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点
- 客户端程序不需要关心对象的创建细节,需要哪个对象时只需要向对应的工厂索要即可, 客户端只负责
消费
,工厂只负责生产
- 如果想进行产品扩展,只需要添加一个具体产品类和一个具体工厂类,不需要修改原来的代码符合OCP原则
工厂方法模式的缺点
- 每次增加一个产品时都需要增加一个具体类和对象实现工厂, 使得系统中类的个数成倍增加导致系统的复杂度增加,同时也增加了系统具体类的依赖
工厂方法模式的角色包括:抽象工厂角色(生产多种武器)
, 具体工厂角色(一个工厂对应生产一种武器)
, 抽象产品角色
, 具体产品角色
//抽象工厂角色: 专门生产各种武器的工厂
public interface WeaponFactory {
Weapon get();
}
//具体工厂角色:专门生产枪的工厂
public class GunFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Gun();
}
}
//具体工厂角色:专门生成飞机的工厂(工厂也可以通过简单工厂模式封装成一个大工厂,然后调用其的静态方法创建对应的工厂)
public class FighterFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Fighter();
}
}
// 抽象产品角色: 武器类
public abstract class Weapon {
// 所有武器都有攻击行为
public abstract void attack();
}
// 具体产品角色:枪
public class Gun extends Weapon{
@Override
public void attack() {
System.out.println("开枪射击!");
}
}
// 具体产品角色:战斗机
public class Fighter extends Weapon{
@Override
public void attack() {
System.out.println("战斗机发射核弹!");
}
}
编写测试程序,获取对应的工厂创建对应的产品
public class Client {
public static void main(String[] args) {
// 这里的new GunFactory()可以采用简单工厂模式进行隐藏,调用WeaponFactory的静态方法根据传递的参数创建对应的工厂
WeaponFactory factory = new GunFactory();
Weapon weapon = factory.get();
weapon.attack();
WeaponFactory factory1 = new FighterFactory();
Weapon weapon1 = factory1.get();
weapon1.attack();
}
}
新增一个匕首产品类
只需要新增一个该产品对应的匕首工厂
即可
// 具体产品角色:匕首
public class Dagger extends Weapon{
@Override
public void attack() {
System.out.println("切割!");
}
}
//具体工厂角色:专门生产匕首的工厂
public class DaggerFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Dagger();
}
}
// 测试生产新增的产品类
public class Client {
public static void main(String[] args) {
WeaponFactory factory2 = new DaggerFactory();
Weapon weapon2 = factory2.get();
weapon2.attack();
}
}
抽象工厂模式
工厂方法模式是针对一个产品等级结构(一个产品系列一个工厂类),而抽象工厂模式是针对多个产品等级结构(多个产品系列一个工厂类)
抽象工厂模式的优点
- 可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
- 一个抽象工厂类可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例
抽象工厂模式缺点
- 产品族扩展非常困难,要增加一个系列的某一产品,既要在AbstractFactory里加代码,又要在具体的里面加代码
抽象工厂中包含4个角色:抽象工厂角色, 具体工厂角色, 抽象产品角色, 具体产品角色
抽象产品角色:武器产品族,水果产品族
public abstract class Weapon {
// 所以武器都有攻击行为
public abstract void attack();
}
public abstract class Fruit {
// 所有果实都有一个成熟周期
public abstract void ripeCycle();
}
具体产品角色:武器产品族
// 武器产品族中的产品等级1
public class Gun extends Weapon{
@Override
public void attack() {
System.out.println("开枪射击!");
}
}
// 武器产品族中的产品等级2
public class Dagger extends Weapon{
@Override
public void attack() {
System.out.println("切割!");
}
}
// 水果产品族中的产品等级1
public class Orange extends Fruit{
@Override
public void ripeCycle() {
System.out.println("橘子的成熟周期是10个月");
}
}
package com.powernode.product;
// 水果产品族中的产品等级2
public class Apple extends Fruit{
@Override
public void ripeCycle() {
System.out.println("苹果的成熟周期是8个月");
}
}
抽象工厂角色: 既能生产武器又能生产水果
public abstract class AbstractFactory {
public abstract Weapon getWeapon(String type);
public abstract Fruit getFruit(String type);
}
具体工厂角色: 武器族工厂, 水果族工厂,根据用户提供的名称创建具体的产品
// 武器族工厂
public class WeaponFactory extends AbstractFactory{
public Weapon getWeapon(String type){
if (type == null || type.trim().length() == 0) {
return null;
}
if ("Gun".equals(type)) {
return new Gun();
} else if ("Dagger".equals(type)) {
return new Dagger();
} else {
throw new RuntimeException("无法生产该武器");
}
}
@Override
public Fruit getFruit(String type) {
return null;
}
}
// 水果族工厂
public class FruitFactory extends AbstractFactory{
@Override
public Weapon getWeapon(String type) {
return null;
}
public Fruit getFruit(String type){
if (type == null || type.trim().length() == 0) {
return null;
}
if ("Orange".equals(type)) {
return new Orange();
} else if ("Apple".equals(type)) {
return new Apple();
} else {
throw new RuntimeException("我家果园不产这种水果");
}
}
}
测试程序
public class Client {
public static void main(String[] args) {
// 客户端调用方法时只面向AbstractFactory调用方法
AbstractFactory factory = new WeaponFactory();
Weapon gun = factory.getWeapon("Gun");
Weapon dagger = factory.getWeapon("Dagger");
gun.attack();
dagger.attack();
AbstractFactory factory1 = new FruitFactory();
Fruit orange = factory1.getFruit("Orange");
Fruit apple = factory1.getFruit("Apple");
orange.ripeCycle();
apple.ripeCycle();
}
}