设计模式之工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangcc233/article/details/86477289

技术交流群:365814763

java设计模式之工厂模式

先思考一个问题,假如你去购买思域车,输入一个数字,比如10或者其他,销售店就对应输出相对应的车型,比如思域10代等。

这个问题该如何解决?

public class BuyCar {

    /**
     * 最简单的实现方式如下
     */
    public static void main(String[] arg) {
        System.out.println("请输入你要购买的思域车型");
        Scanner scanner = new Scanner(System.in);
        String carType = scanner.next();
        Car car = null;
        if ("10".equals(carType)) {
            System.out.println("思域10代,15W,请付款");
            car = new SYten();
        } else if ("9".equals(carType)) {
            System.out.println("思域9代,9W,请付款");
            car = new SYnight();
        } else if ("8".equals(carType)) {
            System.out.println("思域8代,8W,请付款");
            car = new SYeight();
        } else if ("7".equals(carType)) {
            System.out.println("思域7代,7W,请付款");
            car = new SYseven();
        } else if ("6".equals(carType)) {
            System.out.println("思域6代,6W,请付款");
            car = new SYsix();
        }
    }
}

此方案能解决当前的问题,完全是面向实现编程,而不是OO编程,编程大忌- -!

如何用简单工厂模式来修改此代码,使代码可读性增强呢?

public class SYCarFactory {
    public static Car cteateCar(String carType) {
        if ("10".equals(carType)) {
            return new SYten();
        } else if ("9".equals(carType)) {
            return new SYnight();
        } else if ("8".equals(carType)) {
            return new SYeight();
        } else if ("7".equals(carType)) {
            return new SYseven();
        } else if ("6".equals(carType)) {
            return new SYsix();
        }
        return null;
    }

    public static void main(String[] arg) {
        System.out.println("请输入你要购买的思域车型");
        Scanner scanner = new Scanner(System.in);
        String carType = scanner.next();
        Car car = cteateCar(carType);
        car.showCar();
    }
}

 只需要把new 的部分也就是实例化对象的部分,抽取到一个具体类,直接调用。这么做更像是一个编程习惯。

优点:

       1、降低代码的耦合度,将变动与不变动的部分分离开。

       2、将具体构建方法放到具体类,而非抽象类或接口。而抽象类中有一个非常重要的方法,createCar(),然后再

利用if else 或 switch判断需要创建的类型。

缺点:

扫描二维码关注公众号,回复: 4945842 查看本文章

      1、子类膨胀。如果需要购买其他类型的车型,比如思域11代,那么就需要再创建一个思域11代的子类

      2、简单工厂模式仅仅是将创建方法放到具体类中,不能达到面向抽象或面向接口编程的目的。

在简单工厂方法中,也可以解决问题,而且相对于一开始的面向实现编程似乎会好的一点,但创建方法仍然在具体类中,而不是

抽象类或者接口中,那么拓展性就比较差,每个实例化对象也都在具体类中完成,那么如何解决这两个问题(拓展性差和将实例

化对象方法推迟到子类去)。

工厂方法模式:

工厂方法模式定义了一个接口,但由子类决定要实例化的类是哪一个。工厂方法模式是将实例化方法推迟到子类中。

工厂方法模式先建立一个接口,每个子类工厂实现接口并实现方法。如图所示

 创建类:

public interface SYFactory {
    Car showCar();
}

class SYtenFactory implements SYFactory {
    @Override
    public Car showCar() {
        return new SYten();
    }
}
class SYnightFactory implements SYFactory {
    @Override
    public Car showCar() {
        return new SYnight();
    }
}

class SYeightFactory implements SYFactory{
    @Override
    public Car showCar() {
        return new SYeight();
    }
}
class SYsevenFactory implements SYFactory {
    @Override
    public Car showCar() {
        return new SYseven();
    }
}

class SYsixFactory implements SYFactory {
    @Override
    public Car showCar() {
        return new SYsix();
    }
}

class SYCar{
    public Car getSYCar(String carType){
        Car car = null;
        if ("10".equals(carType)) {
            return new SYtenFactory().showCar();
        } else if ("9".equals(carType)) {
            return new SYnightFactory().showCar();
        } else if ("8".equals(carType)) {
            return new SYeightFactory().showCar();
        } else if ("7".equals(carType)) {
            return new SYsevenFactory().showCar();
        } else if ("6".equals(carType)) {
            return new SYsixFactory().showCar();
        }
        return car;
    }
}

客户端测试代码:

public class Test {
    public static void main(String[] arg){
        System.out.println("请输入你要购买的思域车型");
        Scanner scanner = new Scanner(System.in);
        SYCar syCar = new SYCar();
        Car car = syCar.getSYCar(scanner.next());
        car.showCar();
    }
}

工厂方法模式是将实例化对象的过程推迟到子类就完成了。如同在定义中所说的:工厂方法让子类决定要实例化的类是哪一个。

希望不要理解错误,所谓的“决定”,并不是指模式允许子类本身在运行时做决定,而是指在编写创建者类时,不需要知道实际创

建的产品是哪一个。选择使用哪个子类,自然就决定了实际

创建的产品是什么。

优点:

        1、遵循设计原则:要依赖接口,而不是依赖具体类。即将实例化产品的方法从具体类中抽取到接口中,让子类实现接口并实例化子类 。

        2、即可以降低耦合度,实现了接口编程,而非面向实现编程 。

        3、增加一个子类时,只需要实现工厂接口即可使用

缺点:

        1、很明显,子类膨胀问题依然存在。

此时解决问题已经足够,但如果需求要我们也能购买非本田车型的车,比如飞度,那此时改如何解决?

抽象工厂模式:提供一个接口,用户创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客

户就从具体的产品中被解耦。抽象工厂模式就是用来解决产品族的问题。所谓产品族其实就是不同产品等级结构中相关联的产品

组成的一个家族,即产品族。 具体来说现在销售店不仅仅只有思域,还有飞度等车型。思域和飞度都是本田下不同车型的两个产

品,即不同的等级结构,而思域又有自己的车型产品(十代,九代等),飞度也是。故而构成一个产品家族。

 如图所示

 具体代码

interface SYFactory {
    void show();
}

interface FDFactory {
    void show();
}

class SYFactoryImpl implements SYFactory {
    @Override
    public void show() {
        System.out.println("我是思域车厂商");
    }
}

class FDFactoryImpl implements FDFactory {
    @Override
    public void show() {
        System.out.println("我是飞度车厂商");
    }
}

public abstract class BTFactory {
    public abstract SYFactory createSY();

    public abstract FDFactory createFD();
}

class BTFactoryImpl extends BTFactory{
    @Override
    public SYFactory createSY() {
        return new SYFactoryImpl();
    }

    @Override
    public FDFactory createFD() {
        return new FDFactoryImpl();
    }
}

测试代码

public static void main(String[] arg) {
    BTFactory btFactory = new BTFactoryImpl();
    btFactory.createFD().show();
    btFactory.createSY().show();
}

抽象工厂模式优点:

1、具备工厂方法模式的所有特点(即工厂方法模式的升级版)

2、最主要的优点就是可以在类的内部对产品族进行约束

缺点:

非常明显。产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修

改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

总结:
1、所有的工厂都是用来封装对象的创建。
2、简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户的具体类解耦。
3、工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
4、抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
5、所有的工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
6、工厂是很有威力的技巧,帮助我们针对抽象编程,而不是针对具体类编程

猜你喜欢

转载自blog.csdn.net/zhangcc233/article/details/86477289