设计模式开篇之作,简单介绍一下抽象工厂设计模式
前言
试想一下,国内有两个工厂,工厂1和工厂2,这两个不同牌子的工厂生产同样类型的商品,但是商品的价格和数量不一致,这时候我们要对其进行设计,该如何设计呢?
设计思路
- 首先我们需要抽离出两个工厂的共性形成一个抽象类,AbstractFactory其中有两个方法,生产产品A和产品B,也就是CreateProductA() 和CreateProductB()之后通过继承的方式创建两个工厂类,ConcreteFactory1 和ConcreteFactory2,同样继承了这两个方法。
- 其次我们需要对产品进行抽象,针对不同的产品创建不同的抽象类,里面可以配置价格、数量等参数,也可以配置一些抽象方法。然后根据工厂类去编写产品的实现类。也就是ProductA1、ProductA2、ProductB1、ProductB2
- 接下来我们在ConcreteFactory1 工厂中的CreateProductA和CreateProductB方法里分别创建ProductA1和ProductB1,也就是代表了工厂1生产的产品A和产品B,同样的操作适用于ConcreteFactory2 工厂
- 最后调用时,我们先创建抽象工厂的实现类也就是先创建工厂1或者工厂2的实例对象,然后通过调用CreateProductA或者CreateProductB方法去生成该工厂的产品类。
抽象工厂(Abstract Factory):
核心,与商业逻辑无关
具体工厂(Concrete Factory):
在客户端的调用下创建产品的实例,含有选择合适的产品对象的逻辑(与商业逻辑有关)
抽象产品(Abstract Product):
担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product):
抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
代码实现
冰箱抽象类
/**
* 冰箱抽象类。
* @author zygswo
*
*/
public abstract class Fridge {
public abstract void sell(); //销售
public abstract void saveFood(); //保存食物
}
海尔冰箱实现类
public class HaierFridge extends Fridge{
@Override
public void sell() {
System.out.println("海尔 冰箱出售");
}
@Override
public void saveFood(Food food) {
System.out.println("海尔 冰箱保存了食物");
}
}
美的冰箱实现类
public class MediaFridge extends Fridge{
@Override
public void sell() {
System.out.println("美的 冰箱出售");
}
@Override
public void saveFood() {
System.out.println("美的 冰箱保存了食物");
}
}
洗衣机抽象类
/**
* 洗衣机抽象类。
* @author zygswo
*
*/
public abstract class WashingMachine {
public abstract void sell(); //销售
public abstract void washClothes(); //保存食物
}
海尔洗衣机实现类
public class HaierWashingMachine extends WashingMachine{
@Override
public void sell() {
System.out.println("海尔 洗衣机出售");
}
@Override
public void washClothes(Cloth cloth) {
System.out.println("海尔 洗衣机洗" + cloth.getName());
}
}
美的洗衣机实现类
public class MediaWashingMachine extends WashingMachine{
@Override
public void sell() {
System.out.println("美的 洗衣机出售");
}
@Override
public void washClothes(Cloth cloth) {
System.out.println("美的 洗衣机洗" + cloth.getName());
}
}
工厂抽象类
public interface ApplianceManufacturer {
Fridge createFridge();
WashingMachine createWashingMashine();
}
海尔工厂类
public class HaierFactory implements ApplianceManufacturer{
@Override
public Fridge createFridge() {
return new HaierFridge();
}
@Override
public WashingMachine createWashingMashine() {
return new HaierWashingMachine();
}
}
美的工厂类
public class MediaFactory implements ApplianceManufacturer{
@Override
public Fridge createFridge() {
return new MediaFridge();
}
@Override
public WashingMachine createWashingMashine() {
return new MediaWashingMachine();
}
}
主函数
public class MainEntrance {
public static void main(String[] args) {
Fridge haierFridge = new HaierFactory().createFridge();
haierFridge.sell();
haierFridge.saveFood();
Fridge mediaFridge = new MediaFactory().createFridge();
mediaFridge.sell();
mediaFridge.saveFood();
}
}
抽象工厂的优缺点
优势:
- 创建新的产品族,支持“对扩展开放,对修改关闭”的原则。
- 满足不同的工厂生成不同的商品的功能需求。
- 实现了产品和工厂的解耦,产品的功能可以统一配置。
劣势: - 如果需要调整新增产品的功能,需要修改所有工厂产品实现类,会比较繁琐。
应用场景
- 应用于一个系统有多个产品族,且系统只消费其中一个或多个产品族
- 应用于不需要了解产品实现细节,只需要知道产品工厂和产品名称。
其他两种工厂模式
简单工厂
通过往工厂类传参来判断生成哪个具体产品类。
例子: 如图所示,运算类为抽象产品类,加法、减法、乘法、除法类为具体产品类,往createOperate(String opeName) 传参,通过传入的参数opeName来判断该生成哪个具体产品类。之后调用产品类的GetResult方法来获取结果。
优点:简单易懂,适用于产品数量较少的场景
缺点:不满足开闭原则,如果有新的产品要配置就要修改工厂类。
工厂方法:
将具体的产品类生成逻辑交给抽象工厂类的子类来实现,一个工厂类对应一个产品类,以上述的运算工厂为例,工厂方法设计模式如下图:
优点:适用于产品数量较多的场景,满足开闭原则,如果有新的产品要配置可以新增工厂类和产品类。
缺点:如果抽象产品类需要添加新的运算,改动较大。