设计模式(4)简单工厂和工厂模式

首先是简单工厂,它其实不是一种设计模式,更像是一种编程习惯。

假设我们需要生产一部手机,这个手机可以是2017年的新款,也可以是2018年的新款,根据我们的需要,生产出手机。所有的手机都继承一个手机基类,我们可以把手机对象创建的过程提取出来,创造一个工厂从工厂中根据需求返回需要的手机。

代码如下

public class PhoneFactory {

    public static PhoneBase getPhone(PhoneTypeEnum phoneType) {
        PhoneBase phone = null;
        switch (phoneType) {
            case STYLE_2017:
                phone = new Phone_2017();
                break;
            case STYLE_2018:
                phone = new Phone_2018();
                break;
            case STYLE_2019:
                phone = new Phone_2019();
                break;
                default:
                    System.out.println("不存在的手机类型");
        }
        return phone;
    }
}
PhoneFactory
public class PhoneBase {
    public void display() {
        System.out.println("这是一款手机");
    }
}
PhoneBase
public enum PhoneTypeEnum {
    /**
     * 2017新款
     */
    STYLE_2017("2017新款","0"),
    /**
     * 2018新款
     */
    STYLE_2018("2018新款","0"),
    /**
     * 2019新款
     */
    STYLE_2019("2019新款","0"),
    ;

    PhoneTypeEnum(String caption, String value) {
        this.caption = caption;
        this.value = value;
    }

    private String caption;

    private String value;
}
PhoneTypeEnum
public class Phone_2017 extends PhoneBase {
    @Override
    public void display() {
        System.out.println("这是2017年的新款手机");
    }
}
Phone_2017
public class Phone_2018 extends PhoneBase {
    @Override
    public void display() {
        System.out.println("这是2018年的新款手机");
    }
}
Phone_2018
public class Phone_2019 extends PhoneBase {
    @Override
    public void display() {
        System.out.println("这是2019年的新款手机");
    }
}
Phone_2019

测试

public class Main {

    public static void main(String[] args) {
        PhoneBase phone1 = PhoneFactory.getPhone(PhoneTypeEnum.STYLE_2017);
        phone1.display();
        PhoneBase phone2 = PhoneFactory.getPhone(PhoneTypeEnum.STYLE_2018);
        phone2.display();
        PhoneBase phone3 = PhoneFactory.getPhone(PhoneTypeEnum.STYLE_2019);
        phone3.display();
    }
}
测试

输出结果

简单工厂把对象的创建和使用区分开来,让整个程序结构更明确。但是工厂中聚合所有的手机创建过程,每次添加一款手机,就需要改动工厂类。

当然手机不可能只有一个公司的,现在有大米公司和香蕉公司两个公司的手机,如果我需要大米公司2019款和香蕉公司2017款的手机,该如何实现呢?这时候就用到了工厂模式。

首先是创建手机的基类,所有的手机都继承于它,然后是创建手机工厂基类,大米和香蕉两个公司的手机工厂类都继承它,然后各自实现制造手机的方法。

代码如下

public class PhoneBase {
    public void display() {
        System.out.println("这是一款手机");
    }
}
BasePhone
public abstract class BasePhoneFactory {

    /**
     * 制造工艺
     */
    public void productionTechnology() {
        System.out.println("使用最基础的制造工艺");
    }

    /**
     * 生产手机
     * @param phoneType 类型
     * @return 手机
     */
    public abstract BasePhone createPhone(PhoneTypeEnum phoneType);
}
BasePhoneFactory
public enum PhoneTypeEnum {
    /**
     * 2017新款
     */
    STYLE_2017("2017新款","0"),
    /**
     * 2018新款
     */
    STYLE_2018("2018新款","0"),
    /**
     * 2019新款
     */
    STYLE_2019("2019新款","0"),
    ;

    PhoneTypeEnum(String caption, String value) {
        this.caption = caption;
        this.value = value;
    }

    private String caption;

    private String value;
}
PhoneTypeEnum
public class Banana2017 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是香蕉公司2017年款手机");
    }
}

public class Banana2018 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是香蕉公司2018年款手机");
    }
}

public class Banana2019 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是香蕉公司2019年款手机");
    }
}
BananaPhone
public class DaMi2017 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是大米公司2017年款手机");
    }
}

public class DaMi2018 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是大米公司2018年款手机");
    }
}

public class DaMi2019 extends BasePhone {
    @Override
    public void display() {
        System.out.println("这是大米公司2019年款手机");
    }
}
DaMiPhone
public class BananaFactory extends BasePhoneFactory {
    @Override
    public void productionTechnology() {
        System.out.println("使用了香蕉公司独特的制造工艺!");
    }

    @Override
    public BasePhone createPhone(PhoneTypeEnum phoneType) {
        BasePhone phone = null;

        switch (phoneType) {
            case STYLE_2017:
                phone = new Banana2017();
                break;
            case STYLE_2018:
                phone = new Banana2018();
                break;
            case STYLE_2019:
                phone = new Banana2019();
                break;
            default:
                System.out.println("不存在的手机类型");
        }

        if (phone != null) {
            this.productionTechnology();
        }

        return phone;
    }
}
BananaFactory
public class DaMiFactory extends BasePhoneFactory {
    @Override
    public void productionTechnology() {
        System.out.println("使用了大米公司独特的制造工艺!");
    }

    @Override
    public BasePhone createPhone(PhoneTypeEnum phoneType) {
        BasePhone phone = null;

        switch (phoneType) {
            case STYLE_2017:
                phone = new DaMi2017();
                break;
            case STYLE_2018:
                phone = new DaMi2018();
                break;
            case STYLE_2019:
                phone = new DaMi2019();
                break;
            default:
                System.out.println("不存在的手机类型");
        }

        if (phone != null) {
            this.productionTechnology();
        }

        return phone;
    }
}
DaMiFactory

测试

public class Main {
    public static void main(String[] args) {
        BasePhoneFactory factory1 = new BananaFactory();
        BasePhone phone1 = factory1.createPhone(PhoneTypeEnum.STYLE_2017);
        phone1.display();

        BasePhoneFactory factory2 = new DaMiFactory();
        BasePhone phone2 = factory2.createPhone(PhoneTypeEnum.STYLE_2019);
        phone2.display();
    }
}

输出

如果我们需要蓝绿公司2018年款的手机时,因为基类已经定义好了方法,只需要再创建蓝绿公司的手机工厂就能够实现。

原文地址:https://www.cnblogs.com/oeleven/p/10468322.html