欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

工厂方法设计模式

程序员文章站 2024-02-26 18:53:40
...

一、例举

物美超市搞促销活动,促销活动有很多:买二赠一、满3件8折、满100减10等,一般的设计思路是:给每种促销活动写一个计算类,再写一个简单工厂来生产各种促销算法类来解耦客户端与活动实现类,例如:

// 活动
public interface Activity {
    float calculate(float money);
}

// 满减
public class ManJian implements {
    public float calculate(float money) {
        // 满减金额计算
    }
}

// 打折
public class Discount implements {
    public float calculate(float money) {
        // 折扣金额计算
    }
}

public class SaleFactory {
    public Activity getSaleActivity(String sale) {
        switch(sale) {
            case "满减":
                return new ManJian();
                break;
            case "折扣":
                return new Discount();
                break;
        }
    }
}

以上这种方法也是比较常用的一种方法,但是有个问题,如果新添加一种促销活动,比如来个“买一赠一”怎么办,你会说在swich中再加一个case呗,再来一个呢,再来一个呢,再。。。。来一个,一直在里面加,有没有感觉这样有什么不好,说好的“对修改封闭,对扩展开放”呢? 那我们怎样修改呢,那我们可不可以找一种可以不用修改之前的类,只通过扩展来进行创建的方式呢,尝试一下:

// 活动
public interface Activity {
    float calculate(float money);
}

// 满减
public class ManJian implements {
    public float calculate(float money) {
        // 满减金额计算
    }
}

// 打折
public class Discount implements {
    public float calculate(float money) {
        // 折扣金额计算
    }
}

// 促销抽象工厂
public abstract class Factory {
    protected abstract Activity factoryMethod();

    public Activity getActivity() {
        return factoryMethod();
    }
}

// 满减促销工厂
public class ManJianFactory {
    protecte Activity factoryMethod() {
        return new ManJian();
    }
}

// 折扣促销工厂
public class DiscountFactory {
    protecte Activity factoryMethod() {
        return new Discount();
    }
}

// 客户端
public class Client {
    public static void main() {
        float money = 200;
        Factory factory = new DiscountFactory();
        Activity activity = factory.getActivity();
        float result = activity.calcute();
    }
}

该实现方法就是“工厂方法设计模式”。

二、用来解决的问题

工厂方法解决的问题是针对简单工厂来说的,简单工厂一旦需要生产新产品就需要修改工厂类的方法逻辑,违背了“开放封装原则”,而工厂方法模式把具体产品的创建推迟到具体工厂中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样真正做到了“对扩展开放,对修改封闭”。

三、定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工场方法使一个类的实例化延迟到其子类。

四、UML说明

工厂方法设计模式

  • Product:抽象产品
  • ConcreateProduct:具体产品
  • Creator:抽象工厂方法,用来返回具体的产品
  • ConcreteCreator:具体工厂方法

五、使用场景

  • 如果一个类需要创建某个接口对象,但是又不知道具体的的实现,这种情况可以选用工厂方法,将创建对象的工作延迟到子类。
  • 如果一个类本身就希望由它的子类来创建所需要的对象的时候,应该使用工厂方法。

六、优缺点对比(与简单工厂对比)

优点

  • 更符合开-闭原则:增加一个新产品时不用修改之前工厂的判断逻辑。
  • 更符合单一职责:简单工厂中的创建方法存在复制的switch判断

缺点

每添加一个产品,除了要创建产品类还要多创建一个工厂实现类,类的个数增加,一定程序上增加了系统复杂度,而且会有更多的类需要编译运行,增加编译成本。