写在前面:本文是个人在学习设计模式时的所思所想,汇总了其他博主及自己的感悟思考,可能存在出入,请大家理性食用~~
工厂模式
在工厂模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理全部交给子类负责。这样就可以将生成实例的框架和实际负责生成实例的类解耦。
核心:
- 实例化对象不使用new,用工厂方法创建对象。
- 使用工厂统一管理对象的创建,将调用者跟实现类解耦。
1.1. 简单工厂模式
简单工厂模式又叫静态工厂方法模式(因为工厂类定义了一个静态方法)
简单工厂模式的角色包括三个:
- 抽象产品角色
- 具体产品角色
- 工厂类角色
- 抽象产品角色:
public interface Weapon{//所有的武器都有攻击行为public void attack();
}
- 具体产品角色:
//坦克(具体产品角色)
public class Tank implements Weapon{@Overridepublic void attack() {System.out.println("坦克开炮!");}
}
// 战斗机(具体产品角色)
public class Fighter implements Weapon{@Overridepublic void attack() {System.out.println("战斗机投下原子弹!");}
}
//匕首(具体产品角色)
public class Dagger implements Weapon{@Overridepublic void attack() {System.out.println("砍他丫的!");}
}
- 工厂类角色:
//工厂类角色
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 if ("DAGGER".equals(weaponType)) {weapon = new Dagger();} 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();Weapon weapon3 = WeaponFactory.get("DAGGER");weapon3.attack();}
}
优点:实例化具体对象不需要关系具体细节,直接根据参数从工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”。生产和消费分离。
缺点:
-
- 工厂类集中负责所有的创造逻辑,不能出问题,一旦出问题,整个系统瘫痪。
- 不符合OCP开闭原则,在进行系统拓展时,需要修改工厂类。
1.2. 工厂方法模式
工厂方法模式既保留了简单工厂的优点,同时又解决了简单工厂的缺点。
工厂方法模式的角色包括四个:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
- 抽象产品角色:
//武器类(抽象产品角色)
public abstract class Weapon {//所有武器都有攻击行为public abstract void attack();
}
- 具体产品角色:
//具体产品角色
public class Gun extends Weapon{@Overridepublic void attack() {System.out.println("开枪射击!");}
}
//具体产品角色
public class Fighter extends Weapon{@Overridepublic void attack() {System.out.println("战斗机发射核弹!");}
}
- 抽象工厂角色:
//武器工厂接口(抽象工厂角色)
public interface WeaponFactory {Weapon get();
}
- 具体工厂角色:
public class GunFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Gun();}
}
public class FighterFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Fighter();}
}
- 客户端程序:
public class Client {public static void main(String[] args) {//实例化不同的工厂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{@Overridepublic void attack() {System.out.println("砍丫的!");}
}
public class DaggerFactory implements WeaponFactory{@Overridepublic Weapon get() {return new Dagger();}
}
- 客户端程序:
public class Client {public static void main(String[] args) {//实例化不同的工厂WeaponFactory factory = new GunFactory();Weapon weapon = factory.get();weapon.attack();WeaponFactory factory1 = new FighterFactory();Weapon weapon1 = factory1.get();weapon1.attack();WeaponFactory factory2 = new DaggerFactory();Weapon weapon2 = factory2.get();weapon2.attack();}
}
因此可以看出在进行功能拓展时,不需要修改之前的源码,显然工厂方法模式更符合OCP原则。
优点:
-
- 拓展性高,如果想增加一个产品,只需新增一个产品类及其对应的工厂类即可。
- 弱化抽象工厂的职责,将具体产品的实现交给其他工厂,职责分工明确。
缺点:
-
- 每次再新增一个产品时,都需要增加一个具体类及其对应的工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
在Spring框架中,BeanFactory使用的是工厂方法模式。
源码位置:
抽象工厂角色Bean Factory:
实现BeanFatory的具体工厂:
实现BeanFatory的具体工厂角色:
1.3. 抽象工厂模式
抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。
抽象工厂方法模式的角色也包括四个:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
类图:
其他实现原理和流程同工厂方法模式。只不过抽象工厂中包含很多个具体的功能,是一个超级工厂父类。