23种设计模式—— 工厂设计模式

定义:

定义了一个创建产品对象的工厂接口,将实际创建工作推迟到子类工厂当中。

场景模拟:

一个面条项目的方案设计
面条项目:要方便面条品种的扩展,要便于维护,要能运行时扩展

面条类设计:
这里写图片描述

面条工厂设计:if....else if....else

一、普通oop设计方式

/*
 * 面条父类
 */
public abstract class Noodles {
    // 面条名称
    String name;
    // 每种面条制作方式不同,声明为抽象方法
    public abstract void make();
    // 模拟定义为每种面条打包方式一致
    public void box() {
        System.out.println(name + " 打包;");
    }
}


/*
 * 麻辣面
 */
public class MLNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "麻辣面";
        System.out.println(name + "制作;");
    }
}


/*
 * 牛肉面
 */
public class BeefNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "牛肉面";
        System.out.println(name + "制作;");
    }
}


/*
 * 兰州拉面
 */
public class LZNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "兰州拉面";
        System.out.println(name + "制作;");
    }
}


/*
 * 面条订单
 */
public class OrderNoodles {
    public OrderNoodles() {
        Noodles noodles = null;
        String ordertype;
        do {
            ordertype = gettype();

            if (ordertype.equals("ml")) {
                // 选择了麻辣面
                noodles = new MLNoodles();
            } else if (ordertype.equals("beef")) {
                // 选择了牛肉面
                noodles = new BeefNoodles();
            } else if (ordertype.equals("lz")) {
                // 选择了兰州拉面
                noodles = new LZNoodles();
            } else {
                break;
            }
            noodles.box();
        } while (true);
    }


    private String gettype() {
        //接收用户选择
        Scanner scan = new Scanner(System.in);
        System.out.println("请选择您要点的面");
        String str = scan.next();
        return str;
    }
}


/*
 * 主方法测试
 */
public class NoodlesStroe {
    public static void main(String[] args) {
        OrderNoodles orderNoodles;
        orderNoodles = new OrderNoodles();

    }

}

总结:
目前的需求解决了,但是一旦新增面条种类,需要修改订单部分的代码,违反了java开闭原则(Open Close Principle),不合理。

二、简单工厂模式:定义一个实例化面条的类,封装创建对象的代码

/*
 * 面条父类同上
 */


/*
 * 简单工厂
 */
public class SimpleNoodlesFactory {

    //实例化面条对象
    public Noodles CreateNoodles(String ordertype) {
        Noodles noodles = null;

        if (ordertype.equals("ml")) {
            // 选择了麻辣面
            noodles = new MLNoodles();
        } else if (ordertype.equals("beef")) {
            // 选择了牛肉面
            noodles = new BeefNoodles();
        } else if (ordertype.equals("lz")) {
            // 选择了兰州拉面
            noodles = new LZNoodles();
        } 
        return noodles;

    }

}


/*
 * 面条订单
 */
public class OrderNoodles {
    SimpleNoodlesFactory simpleNoodlesFactory;

    public OrderNoodles(SimpleNoodlesFactory simpleNoodlesFactory) {

        setFactory(simpleNoodlesFactory);
    }

    public void setFactory(SimpleNoodlesFactory simpleNoodlesFactory) {
        Noodles noodles = null;
        String ordertype;

        this.simpleNoodlesFactory = simpleNoodlesFactory;

        do {
            ordertype = gettype();
            noodles = simpleNoodlesFactory.CreateNoodles(ordertype);
            if (noodles != null) {
                noodles.make();
                noodles.box();
            }
        } while (true);

    }

    private String gettype() {
        //接收用户选择
        Scanner scan = new Scanner(System.in);
        System.out.println("请选择您要点的面:");
        String str = scan.next();
        return str;
    }

}


/*
 * 主方法测试
 */
public class NoodlesStroe {
    public static void main(String[] args) {
        //实例化工厂
        SimpleNoodlesFactory simpleNoodlesFactory=new SimpleNoodlesFactory();
        //创建订单
        OrderNoodles orderNoodles;
        orderNoodles = new OrderNoodles(simpleNoodlesFactory);
    }
}

总结:
解决了上个方案遗留的问题,再次新加对象种类时,无需修改订单部分代码。但项目进一步扩展,在不同地区开展加盟店,然而每个地区制作出的口味不同,进而利用工厂方法模式进行设计。

三、工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类(针对每一种产品提供一个工厂类 。通过不同的工厂实例来创建不同的产品实例)

/*
 * 北京牛肉面
 */
public class BJBeefNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "北京牛肉面";
        System.out.println(name+"制作;");
    }
}

/*
 * 北京麻辣面
 */
public class BJMLNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "北京麻辣面";
        System.out.println(name+"制作;");     
    }
}

/*
 * 上海牛肉面
 */
public class SHBeefNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "上海牛肉面";
        System.out.println(name+"制作;");     
    }
}

/*
 * 上海麻辣面
 */
public class SHMLNoodles extends Noodles {
    @Override
    public void make() {
        this.name = "上海麻辣面";
        System.out.println(name+"制作;");     
    }
}


/*
 * 工厂方法模式——抽象订单类
 */
public abstract class OrderNoodles {
    public OrderNoodles() {
        Noodles noodles = null;
        String ordertype;
        do {
            ordertype = gettype();
            noodles = createNoodles(ordertype);
            noodles.make();
            noodles.box();
        } while (true);
    }

    //实例化对象由加盟店具体实例化
    abstract Noodles createNoodles(String ordertype);

    private String gettype() {
        //接收用户选择
        Scanner scan = new Scanner(System.in);
        System.out.println("请选择您要点的面:");
        String str = scan.next();
        return str;
    }
}


/*
 * 北京订单类
 */
public class BJOrderNoodles extends OrderNoodles {
    @Override
    Noodles createNoodles(String ordertype) {
        Noodles noodles = null;
        if (ordertype.equals("ml")) {
            noodles = new BJMLNoodles();
        } else if (ordertype.equals("beef")) {
            noodles = new BJBeefNoodles();
        }
        return noodles;
    }
}


/*
 * 上海订单类
 */
public class SHOrderNoodles extends OrderNoodles {
    @Override
    Noodles createNoodles(String ordertype) {
        Noodles noodles = null;

        if (ordertype.equals("ml")) {
            noodles = new SHMLNoodles();
        } else if (ordertype.equals("beef")) {
            noodles = new SHBeefNoodles();
        }
        return noodles;
    }
}

/*
 * 主方法测试
 */
public class NoodlesStroe {
    public static void main(String[] args) {
        OrderNoodles orderNoodles;
        orderNoodles = new SHOrderNoodles();
    }
}

总结:
此次改进后,只需在主方法中实例化不同的OrderNoodles对象,就可以体验不同地区的Noodles。

四、抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类(抽象工厂往往有多种方法,可以生产多种产品,即产品簇,比如工厂还可以生产饼,汤等等)。

/*
 * 抽象工厂
 */
public interface AbsFactory {
    public Noodles CreateNoodles(String ordertype) ;
}

/*
 * 北京工厂
 */
public class BJFactory implements AbsFactory {
    @Override
    public Noodles CreateNoodles(String ordertype) {
        Noodles noodles = null;
        if (ordertype.equals("ml")) {
            noodles = new BJMLNoodles();
        } else if (ordertype.equals("beef")) {
            noodles = new BJBeefNoodles();
        }
        return noodles;
    }
}

/*
 * 上海工厂
 */
public class SHFactory implements AbsFactory {
    @Override
    public Noodles CreateNoodles(String ordertype) {
        Noodles noodles = null;
        if (ordertype.equals("ml")) {
            noodles = new SHMLNoodles();
        } else if (ordertype.equals("beef")) {
            noodles = new SHBeefNoodles();
        }
        return noodles;
    }
}

/*
 * 抽象工厂模式——订单类
 */
public class OrderNoodles {
    AbsFactory mFactory;

    public OrderNoodles(AbsFactory mFactory) {
        setFactory(mFactory);
    }

    public void setFactory(AbsFactory mFactory) {
        Noodles noodles = null;
        String ordertype;
        this.mFactory = mFactory;
        do {
            ordertype = gettype();
            noodles = mFactory.CreateNoodles(ordertype);
            if (noodles != null) {
                noodles.make();
                noodles.box();
            }
        } while (true);
    }

    private String gettype() {
        //接收用户选择
        Scanner scan = new Scanner(System.in);
        System.out.println("请选择您要点的面:");
        String str = scan.next();
        return str;
    }
}

/*
 * 主方法测试
 */
public class NoodlesStroe {
    public static void main(String[] args) {
        OrderNoodles orderNoodles;
        orderNoodles = new OrderNoodles(new BJFactory());
    }
}

抽象工厂模式与工厂方法模式的区别:

  抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

适用场景:

  无论是简单工厂模式,工厂方法模式还是抽象工厂模式,它们都具有类似的特性,适用场景也十分类似。他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

  所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的产品,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值