Spring常用设计模式-工厂模式

简单工厂模式

简单工厂模式是指由一个工厂对象决定创建哪一种产品类的实例。
以课程为例,假如目前某学院开设Java架构、大数据、人工智能等课程,通常的写法:

public interface ICourse {
    /** 录制视频 */
    public void record();
}

public class JavaCourse implements ICourse {
    @Override
    public void record() {
        System.out.println("录制Java视频");
    }
}

public class PythonCourse implements ICourse {
    @Override
    public void record() {
        System.out.println("录制Python视频");
    }
}

public class Test {
    public static void main(String[] args) {
        ICourse javaCourse = new JavaCourse();
        javaCourse.record();
        ICourse pythonCourse = new PythonCourse();
        pythonCourse.record();
    }
}

Test类需要依赖JavaCourse和PythonCourse,如果还有别的课程,那么Test还将继续依赖,违背了迪米特原则。
现在用简单工厂模式进行优化,首先创建一个CourseFactory工厂类。

public class CourseFactory {
    public ICourse create(String name) {
        if("java".equals(name)) {
            return new JavaCourse();
        } else if("python".equals(name)) {
            return new PythonCourse();
        } else {
            return null;
        }
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        courseFactory.create("java");
        courseFactory.create("python");
    }
}

客户端调用时变简单了,但是工厂类的设计不符合开闭原则,因为如果要增加前端课程,那么工厂的create()方法就要修改代码,继续优化。

public class CourseFactory {
    public ICourse create(String className) {
        if(!(null == className || "".equals(className))) {
            try {
                return (ICourse) Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        ICourse course = courseFactory.create("cn.itdjn.ch2.ch2_2.ch2_2_2.JavaCourse");
        course.record();
    }
}

现在不需要修改CourseFactory中的代码,但方法参数是字符串,可控性有待提升,而且还需要强制类型转换,继续优化。

public class CourseFactory {
    public ICourse create(Class<? extends ICourse> clazz) {
        try {
            if(null != clazz) {
                return clazz.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();
        ICourse course = courseFactory.create(JavaCourse.class);
        course.record();
    }
}

工厂方法模式

定义一个创建对象的接口,让实现这个接口的类决定实例化哪个类,工厂方法模型让类的实例化推迟到子类中进行。简单工厂模式中随着产品链的丰富,可能会出现每个课程创建逻辑上的区别,这个时候单一的简单工厂模式就会变得不易于维护。我们需要根据单一职责原则将职能区分,专人干专事。此时Java课程由Java工厂创建,Python课程由Python工厂创建。

public interface ICourseFactory {
    ICourse create();
}

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        return new JavaCourse();
    }
}

public class PythonCourseFactory implements ICourseFactory {
    @Override
    public ICourse create() {
        return new PythonCourse();
    }
}

public class Test {
    public static void main(String[] args) {
        ICourseFactory factory = new PythonCourseFactory();
        ICourse course = factory.create();
        course.record();

        factory = new JavaCourseFactory();
        course = factory.create();
        course.record();
    }
}

抽象工厂模式

在这里插入图片描述
先解释什么是产品族,上图第一行假设都是美的公司生产的家用电器,那么正方形表示美的冰箱,圆形表示美的空调,菱形表示美的热水器。那么第二行可能就是格力冰箱、格力空调、格力热水器,依次类推。
在解释什么产品等级结构,上图第一列都是冰箱,第二列都是空调,第三列都是热水器,但是每行属于不同的厂家制造的。那厂家不同,工厂也就不一样,所以延伸出下面的图形。
在这里插入图片描述
由上图可以看出,第一行的美的产品是由美的工厂生产的,第二行的格力产品是由格力工厂生产的,这两个工厂是不同的具体工厂。
以上面的电器为例,假如现在要制造冰箱、空调、洗衣机,那么这三个产品是三个不同的产品等级结构。
冰箱、空调、洗衣机接口如下:

/**
 * 空调
 */
public interface IAirConditioner {
    void refrigeration(); // 制冷
}
/**
 * 冰箱
 */
public interface IRefrigerator {
    void coldStorage(); // 冷藏
}
/**
 * 洗衣机
 */
public interface IWashingMachine {
    void washClothes(); // 洗衣服
}

抽象工厂类:

/**
 * 抽象工厂
 */
public interface HomeApplianceFactory {
    IRefrigerator createRefrigerator();
    IAirConditioner createAirConditioner();
    IWashingMachine createWashingMachine();
}

具体不同厂家的冰箱、空调、洗衣机:

/**
 * 美的空调
 */
public class BeautifulAirConditioner implements IAirConditioner {
    @Override
    public void refrigeration() {
        System.out.println("美的空调可以制冷");
    }
}
/**
 * 美的冰箱
 */
public class BeautifulRefrigerator implements IRefrigerator {
    @Override
    public void coldStorage() {
        System.out.println("美的冰箱冷藏食物");
    }
}
/**
 * 美的洗衣机
 */
public class BeautifulWashingMachine implements IWashingMachine {
    @Override
    public void washClothes() {
        System.out.println("美的洗衣机可以洗衣服");
    }
}
/**
 * 格力空调
 */
public class GreeAirConditioner implements IAirConditioner {
    @Override
    public void refrigeration() {
        System.out.println("格力空调可以制冷");
    }
}
/**
 * 格力冰箱
 */
public class GreeRefrigerator implements IRefrigerator {
    @Override
    public void coldStorage() {
        System.out.println("格力冰箱冷藏食物");
    }
}
/**
 * 格力洗衣机
 */
public class GreeWashingMachine implements IWashingMachine {
    @Override
    public void washClothes() {
        System.out.println("格力洗衣机可以洗衣服");
    }
}

具体不同厂家的工厂类:

/**
 * 美的工厂
 */
public class BeautifulFactory implements HomeApplianceFactory {
    @Override
    public IRefrigerator createRefrigerator() {
        return new BeautifulRefrigerator();
    }

    @Override
    public IAirConditioner createAirConditioner() {
        return new BeautifulAirConditioner();
    }

    @Override
    public IWashingMachine createWashingMachine() {
        return new BeautifulWashingMachine();
    }
}
/**
 * 格力工厂
 */
public class GreeFactory implements HomeApplianceFactory{
    @Override
    public IRefrigerator createRefrigerator() {
        return new GreeRefrigerator();
    }

    @Override
    public IAirConditioner createAirConditioner() {
        return new GreeAirConditioner();
    }

    @Override
    public IWashingMachine createWashingMachine() {
        return new GreeWashingMachine();
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        HomeApplianceFactory factory = new BeautifulFactory();
        factory.createAirConditioner().refrigeration();
        factory.createRefrigerator().coldStorage();
        factory.createWashingMachine().washClothes();
        factory = new GreeFactory();
        factory.createAirConditioner().refrigeration();
        factory.createRefrigerator().coldStorage();
        factory.createWashingMachine().washClothes();
    }
}

上述完整的描述了两个产品族,但是如果继续扩展产品等级,比如增加电风扇,那代码从抽象工厂到具体工厂都要调整,这违背了开闭原则,因此抽象工厂也是有缺点的,但是是可接受的,只要不是过于频繁的升级。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章