设计模式--工厂模式

工厂模式

Factory Design Pattern 工厂模式

工厂模式分类:

  • 简单工厂模式

  • 工厂方法模式

  • 抽象工厂模式

示例

披萨生产和销售的项目:

  1. 披萨的种类 GreekPizz、CheesePiz等
  2. 披萨的制作过程有 prepare、bake、cut、box
  3. 完成披萨店订购功能

传统模式

  1. 思路分析(类图)
    在这里插入图片描述
//披萨抽象类
public abstract class Pizza{
    //披萨名字
   	private String name;
    
    public void setName(){
        this.name=name;
    }
    
    public String getName(){
        return this.name;
    }
    //准备方法
    public abstract void prepare();
    //烘培
    public void bake(){
        System.out.println(this.name+" baking");
    }
    //切割
    public void cut(){
        System.out.println(this.name+" cutting");
    }
    //打包
    public void box(){
        System.out.println(this.name+" boxing");
    }
}

//奶酪披萨
public class CheesePizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" 给制作奶酪披萨 准备原材料 ");
	}

}
//希腊披萨
public class GreekPizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" 给希腊披萨 准备原材料 ");
	}

}
//中国披萨
public class CheesePizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" 给制作奶酪披萨 准备原材料 ");
	}

}
//披萨订单类
public class OrderPizza{
    //披萨
    Pizza pizza=null;
    //披萨类型
    String orderType;
    
    /**
     * 获取pizza种类
     * 此处可以根据需求,定义如何获取披萨类型
     * @return
     */
    private String getOrderType() {
        BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("--------------------------------------------------");
        System.out.println("input pizza 种类:");
        String orderType = null;
        try {
            orderType = strIn.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
        return orderType;
    }
    
    public OrderPizza(){
        do{
            //获取披萨类型
            orderType=getOrderType();
            switch(orderType){
                case "greek":
                    pizza=new GreekPizza();
                    pizza.setName(" 希腊披萨 ");
                    break;
                case "cheese":
                    pizza = new CheesePizza();
                    pizza.setName(" 奶酪披萨 ");
                    break;
                case "pepper":
                    pizza = new PepperPizza();
                    pizza.setName(" 胡椒披萨 ");
                    break;
                default:
                    System.out.println("请输入正确的披萨名称");
                    pizza=null;
                    break;
            }
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }
        }while(true);
    }
}
  1. 分析
  • 优点是比较好理解,简单易操作。
  • 缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。
  • 如果新增一种披萨代码修改如下:
//1.新增pizza类
public class PepperPizza extends Pizza {

	@Override
	public void prepare() {
		// TODO Auto-generated method stub
		System.out.println(" 给胡椒披萨准备原材料 ");
	}

}
//2.在订单orderPizza的switch语句中增加新的判断
case "pepper":
	pizza = new PepperPizza();
	pizza.setName(" 胡椒披萨 ");
	break;
	
  1. 改进思路

把创建Pizza对象封装到一个类中,这样我们有新的Pizza类型时,只需要修改该类就可,其他有创建到Pizza对象的代码就不需要修改了。

简单工厂模式

  1. 基本介绍
    • 简单工厂模式是属于创建型模式,是工厂模式的一种,也叫静态工厂模式。
    • 简单工厂模式是定义一个工厂对象的类,由这个类来封装实例化对象的行为代码。
    • 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。
  2. 工厂模式的类图
    在这里插入图片描述
//简单工厂类
public class SimpleFactory {

    /**
     * 简单工厂模式(静态工厂模式)
     *
     * @param orderType
     * @return
     */
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("greek".equals(orderType)) {
            pizza = new GreekPizza();
            pizza.setName(" 希腊披萨 ");
        } else if ("cheese".equals(orderType)) {
            pizza = new CheesePizza();
            pizza.setName(" 奶酪披萨 ");
        } else if ("pepper".equals(orderType)) {
            pizza = new PepperPizza();
            pizza.setName(" 胡椒披萨 ");
        } else {
            pizza = null;
        }
        return pizza;
    }
}
//披萨订单类
public class OrderPizza {
    /**
     * 简单工厂
     */
    SimpleFactory simpleFactory;
    /**
     * 披萨
     */
    Pizza pizza = null;


    public OrderPizza(SimpleFactory simpleFactory) {
        setFactory(simpleFactory);
    }
    
    
    /**
     * 获取pizza种类
     *
     * @return
     */
    private String getOrderType() {
        BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("input pizza 种类:");
        String orderType = null;
        try {
            orderType = strIn.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
        return orderType;
    }


    public void setFactory(SimpleFactory simpleFactory) {
        /**
         * 披萨类型
         */
        String orderType = "";
        this.simpleFactory = simpleFactory;
        do {
            orderType = getOrderType();
            pizza = this.simpleFactory.createPizza(orderType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购pizza失败");
            }
        } while (true);
    }
}
  1. 分析
  • 简单工厂模式解决了披萨对象在订单类中生成,简单工厂类负责创建具体的披萨对象。
  • 在简单工厂类的创建方法中,使用了switch-case结构,违背开闭原则。
  • 在考虑到可读性的前提下,如果能够保证不频繁的增删具体实现类,是可以使用此种设计方式的。
  • 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

工厂方法模式

  1. 基本介绍
    • 工厂方法模式定义了一个创建对象的抽象方法,由子类决定决定实例化的类。
    • 工厂方法模式比着简单工厂模式更符合开闭原则
  2. 工厂方法模式类图
    在这里插入图片描述
//抽象披萨订单
public abstract class AbstractOrderPizza {

    //定义一个抽象方法,createPizza , 让各个工厂子类自己实现
    abstract Pizza createPizza(String orderType);

    
    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
    
    // 构造器
    public AbstractOrderPizza() {
        Pizza pizza = null;
        String orderType; // 订购披萨的类型
        do {
            orderType = getType();
            pizza = createPizza(orderType); //抽象方法,由工厂子类完成
            //输出pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);
    }
}
//北京工厂
public class BJOrderPizzaFactory extends AbstractOrderPizza {


    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

//伦敦工厂
public class LDPizzaFactory extends AbstractOrderPizza {


    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

//披萨店使用
public class PizzaStore {

	public static void main(String[] args) {
		String loc = "bj";
		if (loc.equals("bj")) {
			//创建北京口味的各种Pizza
			new BJPizzaOrderFactory();
		} else {
			//创建伦敦口味的各种Pizza
			new LDOrderPizzaFactory();
		}
	}

}
  1. 分析

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现产品类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行。

抽象工厂模式

  1. 基本介绍
    • 抽象工厂模式定义一个接口用于创建相关或有依赖关系的对象簇
    • 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
    • 从设计层面看抽象工厂模式就是对简单工厂模式的改进(或者进一步的抽象)
  2. 抽象工厂模式类图
    在这里插入图片描述
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //让下面的工厂子类来 具体实现
    public Pizza createPizza(String orderType);
}

//这是工厂子类
public class BJFactory implements AbsFactory {

    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("~使用的是抽象工厂模式~");
        // TODO Auto-generated method stub
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }

}

public class LDFactory implements AbsFactory {

    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("~使用的是抽象工厂模式~");
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }

}

public class OrderPizza {

    AbsFactory factory;

    // 构造器
    public OrderPizza(AbsFactory factory) {
        setFactory(factory);
    }

    private void setFactory(AbsFactory factory) {
        Pizza pizza = null;
        String orderType = ""; // 用户输入
        this.factory = factory;
        do {
            orderType = getType();
            // factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = factory.createPizza(orderType);
            if (pizza != null) { // 订购ok
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购失败");
                break;
            }
        } while (true);
    }

    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

  • 三种设计模式对比者可以更好的理解,先从简单工厂模式开始,然后工厂方法模式,在看抽象工厂模式,了解演变过程。
  • 上图中工厂方法模式和抽象工厂模式都是尚硅谷老师讲解的,极客学院讲解的不太一样,又对照着大话设计模式看了一遍,各有侧重点吧,重要看自己怎么理解啦。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值