目录

工厂模式

简单工厂模式

工厂方法模式

策略模式

工厂+策略模式

工厂模式和策略模式的区别


工厂模式

工厂模式属于创建型设计模式,关注于创建对象。工厂模式的目的是为了解耦,实现创建者和调用者的分离。将创建对象的具体过程更隔离起来,使用者不再需要知道对象创建的细节只需要通过工厂类来请求所需的实例。工厂模式具体有三种:简单工厂模式,工厂方法模式和抽象工厂模式。以造汽车为例:    

简单工厂模式

就是通过一个汽车工厂,根据需求,创建对应的汽车。缺点就是代码中有大量的ifelse,后续若是新增一个汽车,就需要对这个工厂类进行修改,这显然不符合设计模式的开闭原则。于是接下来就有了工厂方法模式。

UML结构图:

代码演示:

产品类

// 抽象汽车类
abstract class Car {
    public Car(){}
}

// 比亚迪汽车类
public class BYDCar extends Car{
    public BYDCar() {
        System.out.println("创建了一辆比亚迪汽车");
    }
}

// 理想汽车类
public class LiXiangCar extends Car{
    public LiXiangCar () {
        System.out.println("创建了一辆理想汽车");
    }
}

汽车工厂类

public class CarFactory {
    public Car createCar(String type) {
        switch (type) {
            case "BYD":
                return new BYDCar();
            case "LiXiang":
                return new LiXiangCar();
            default:
                break;
        }
        return null;
    }
}

测试 

public class Main {
    public static void main(String[] args) {
        // 创建工厂
        CarFactory carFactory = new CarFactory();
        // 创建比亚迪汽车
        Car bydCar = carFactory.createCar("BYD");
        // 创建理想汽车
        Car liXiangCar = carFactory.createCar("LiXiang");
    }
}

结果

工厂方法模式

相较于简单工厂模式,不再是只有单一的一个工厂,而是一种汽车对应一个工厂,一个工厂专门只负责一种汽车的生产。优点是后续增加新的汽车种类,只需要新增一个汽车类和对应的汽车工厂类。没有去修改已有的代码。符合设计模式的开闭原则。缺点就是代码量增加,每新增一个汽车,都要创建对应的汽车类和工厂类。

UML结构图:

代码演示:

产品类

// 汽车抽象类
public abstract class Car {
    public Car(){}
}

// 比亚迪汽车
public class BYDCar extends Car{
    public BYDCar() {
        System.out.println("创建了一辆比亚迪汽车");
    }
}

// 理想汽车
public class LiXiangCar extends Car{
    public LiXiangCar () {
        System.out.println("创建了一辆理想汽车");
    }
}

汽车工厂类

// 工厂公共接口
public interface CarFactory {
    Car createCreate();
}

// 比亚迪汽车生产工厂
public class BYDFactory implements CarFactory {
    @Override
    public Car createCreate() {
        return new BYDCar();
    }
}

// 理想汽车生产工厂
public class LiXiangFactory implements CarFactory{
    @Override
    public Car createCreate() {
        return new LiXiangCar();
    }
}

 测试

public class Main {
    public static void main(String[] args) {
        // 创建比亚迪汽车工厂
        BYDFactory bydFactory = new BYDFactory();
        bydFactory.createCreate();
        LiXiangFactory liXiangFactory = new LiXiangFactory();
        liXiangFactory.createCreate();
    }
}

结果

策略模式

策略模式是一种行为型设计模式,关注的是对象的不同行为。它将不同的算法封装起来,构成不同的行为。在运行时使用者可根据条件动态地选择算法,从而改变对象的行为。主要分为策略接口,策略类,上下文类。如下以购物会员打折为例。不是会员不打折,初级会员打九折,中级会员打八折,高级会员打七折。

UML结构图

策略类

// 策略接口
public interface MemberPriceStrategy {
    // 计算价格的抽象方法
    // 参数,原价和购买数量
    double calcPrice(double originalPrice, int number);
}

// 非会员策略类
public class OrdinaryMemberStrategy implements MemberPriceStrategy{
    @Override
    public double calcPrice(double originalPrice, int number) {
        return originalPrice*number;
    }
}

// 初级会员策略类
public class juniorMemberStrategy implements MemberPriceStrategy{
    @Override
    public double calcPrice(double originalPrice, int number) {
        return originalPrice*number*0.9;
    }
}

// 中级会员策略类
public class IntermediateMemberStrategy implements MemberPriceStrategy {
    @Override
    public double calcPrice(double originalPrice, int number) {
        return originalPrice*number*0.8;
    }
}

//高级会员策略类
public class SeniorMemberStrategy implements MemberPriceStrategy{
    @Override
    public double calcPrice(double originalPrice, int number) {
        return originalPrice*number*0.7;
    }
}

上下文类

/**
 * 上下文
 * 通过创建这个类(传入不同的策略实现类参数),并调用其方法
 * 将策略抽象类作为成员变量,并对外提供一个统一的方法,用户只需要在创建该类时传入不同的策略实现类。
 */

public class MemberContext {

    // 抽象策略接口
    private MemberPriceStrategy memberPriceStrategy;

    // 构造方法,传入具体的会员等级
    public MemberContext(MemberPriceStrategy memberPriceStrategy) {
        this.memberPriceStrategy = memberPriceStrategy;
    }

    // 计算价格
    public double finalPrice(double originalPrice, int number) {
        return memberPriceStrategy.calcPrice(originalPrice,number);
    }
}

测试

public class Main {
    public static void main(String[] args) {
        // 创建上下文,传入非会员策略类
        MemberContext memberContext = new MemberContext(new OrdinaryMemberStrategy());
        double finalPrice = memberContext.finalPrice(20, 10);
        System.out.println(finalPrice);
        // 创建上下文,传入初级会员策略类
        MemberContext memberContext1 = new MemberContext(new juniorMemberStrategy());
        double finalPrice1 = memberContext1.finalPrice(20, 1);
        System.out.println(finalPrice1);
    }
}

工厂+策略模式

工厂模式加策略模式是一种在软件开发中常用的设计模式组合,它结合了工厂模式的创建型特点和策略模式的行为型特点,以提供更为灵活和可扩展的系统设计。

策略类

/**
 * 汽车策略接口
 */
public interface CarStrategy {

    /**
    * 返回枚举值
    */
    CarEnum getCarType();

    /**
    * 创建汽车
    */
    void createCar();

}

/**
 * 比亚迪汽车策略类
 */
@Component 
public class BYDCarStrategy implements CarStrategy{

    @Override
    public CarEnum getCarType() {
        return CarEnum.BYD;
    }

    @Override
    public void createCar() {
        System.out.println("创造BYD汽车");
    }
}

/**
 * 理想汽车策略类
 */
@Component
public class LiXiangCarStrategy implements CarStrategy {

    @Override
    public CarEnum getCarType() {
        return CarEnum.LIXIANG;
    }

    @Override
    public void createCar() {
        System.out.println("创建理想汽车");
    }

}

枚举类 

/**
 * 汽车枚举类
 */
public enum CarEnum {

    BYD(1,"比亚迪"),
    LIXIANG(2,"理想");

    private int code;
    private String desc;

    CarEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public static CarEnum getByCode(int code) {
        for (CarEnum carEnum : CarEnum.values()) {
            if(carEnum.code == code) {
                return carEnum;
            }
        }
        return null;
    }

}

工厂类 

/**
 * 汽车工厂类
 */
@Component
public class CarFactory implements InitializingBean {

    /**
     *使用autowrid自动装配Spring中所有实现了CarStrategy接口的bean对象
     */
    @Autowired
    private List<CarStrategy> carStrategyList;

    /**
     * 存储枚举值与对应的汽车策略类的map集合
     */
    private Map<CarEnum, CarStrategy> carStrategyMap = new HashMap<>();

     /**
     * 在bean初始化时将枚举与对应的策略类存入map集合中
     * 当然也可以使用 @postConstrct注解
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        for (CarStrategy carStrategy : carStrategyList) {
            carStrategyMap.put(carStrategy.getCarType(), carStrategy);
        }
    }

    /**
     * 对外提供调用的方法,通过传入type,返回一个具体的策略
     */
    public CarStrategy getCarStrategy(int code) {
        CarEnum carEnum = CarEnum.getByCode(code);
        return carStrategyMap.get(carEnum);
    }

}

测试

@SpringBootTest
class FactoryAndStrategyApplicationTests {

    @Autowired
    private CarFactory carFactory;

    @Test
    void contextLoads() {
        CarStrategy carStrategy = carFactory.getCarStrategy(1);
        carStrategy.createCar();
        CarStrategy carStrategy1 = carFactory.getCarStrategy(2);
        carStrategy1.createCar();
    }

}

 结果

可以看出,根据传入的不同的类型,得到不同的策略类,执行的也是不同的代码。这种模式的好处在于,后续若是有新增车型的需求,那么只需要新创建一个策略类并实现策略接口,再在枚举类中添加相关枚举值。并不会修改原有策略类等代码。完全符合设计模式的开闭原则。

工厂模式和策略模式的区别

类型不同

  • 工厂模式是一种创建型设计模式
  • 策略模式是一种行为型设计模式

结构不同

  • 工厂模式通常包括抽象工厂、具体工厂、抽象产品和具体产品等角色。
  • 策略模式通常包括抽象策略类、具体策略类和上下文类。

关注点不同

  • 工厂模式主要关注于对象的创建过程,通过工厂类来封装对象的创建细节,使调用者与对象的创建解耦
  • 策略模式主要关注的是对象的行为(算法),在运行时根据条件可以动态地选择算法,从而改变对象的行为。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐