尚硅谷设计模式学习---[简单工厂模式,工厂方法模式,抽象工厂模式]

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尚硅谷设计模式学习---[简单工厂模式,工厂方法模式,抽象工厂模式]相关的知识,希望对你有一定的参考价值。

🚀🚀🚀尚硅谷传送门==>B站尚硅谷Java设计模式

❤❤❤感谢尚硅谷❤❤❤

🛴🛴🛴最近开始计划学习一下设计模式了,加油!!!



🚗简单工厂模式

从披萨店的案例引入工厂模式,进入学习

披萨的种类很多(比如 GreekPizza、CheesePizza 等)

  • 披萨的制作有 prepare(准备材料工作),bake(烘烤工作), cut(切片工作), box(包装工作)
  • 完成披萨店订购功能。

先分析传统思路

传统思路代码

披萨类Pizza

//将披萨类定义为抽象类;
public abstract class Pizza {
    //披萨的种类名;
    protected String name;

    //制作披萨时准备原材料的工作;
    public abstract void prepare();

    //烘烤披萨;
    public void bake() {
        System.out.println(name + " 烘焙中...;");
    }

    //披萨切片;
    public void cut() {
        System.out.println(name + " 切片中.....;");
    }

    //披萨包装;
    public void box() {
        System.out.println(name + " 打包....;");
    }

    //为披萨设置种类名;
    public void setName(String name) {
        this.name = name;
    }
}

奶酪披萨类CheesePizza

//奶酪披萨类;
public class CheesePizza extends Pizza{
    @Override
    public void prepare() {
        setName("奶酪披萨");
        System.out.println("奶酪披萨准备材料工作");
    }
}

希腊披萨类GreekPizza

public class GreekPizza extends Pizza{
    @Override
    public void prepare() {
        setName("希腊披萨");
        System.out.println("希腊披萨准备工作");
    }
}

订购披萨类ToOrderPizza

//订购披萨类;
public class ToOrderPizza {
    //初始化时执行构造方法;
    public ToOrderPizza() {
        Pizza pizza = null;
        //订购的种类;
        String orderType;
        do {
            //动态获取订购披萨的种类;
            orderType=gettype();
            if(orderType.equals("CheesePizza")){
                pizza=new CheesePizza();
            }else if(orderType.equals("GreekPizza")){
                pizza=new GreekPizza();
            }else {
                break;
            }
            //进行披萨的制作;
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while (true);
    }

    //输入台获取披萨的种类;
    private String gettype() {
        try {
            BufferedReader strs = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("输入订购的披萨种类:");
            String str = strs.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

披萨店PizzaShop

//披萨店类;
public class PizzaShop {
    public static void main(String[] args) {

        //订购披萨,完成工作;
        new ToOrderPizza();
    }
}

尝试使用;

输入订购的披萨种类:
CheesePizza
奶酪披萨准备材料工作
奶酪披萨 烘焙中...;
奶酪披萨 切片中.....;
奶酪披萨 打包....;
输入订购的披萨种类:
GreekPizza
希腊披萨准备工作
希腊披萨 烘焙中...;
希腊披萨 切片中.....;
希腊披萨 打包....;
输入订购的披萨种类:
qweqw

需要注意的是,如果需要增加另外的披萨种类时,就要去创建新的种类;然后在订购披萨时添加新的依赖;
这样的做法会导致依赖关系复杂;
违反了设计模式的OCP(开闭原则);[对扩展开放,对修改关闭]


引入简单工厂模式进行优化

简单工厂模式作为创建型模式,仅需要一个工厂对象去决定创建的是哪种披萨产品的实例对象即可.

引入一个简单工厂类将创建着各种个披萨实例对象进行封装;
所有的订购披萨类都在这个简单工厂类中创建对象;
保证了扩展新种类披萨后,只需要在简单工厂类中修改即可.

也去避免了在增加新的披萨种类后(即提供方扩展了新的功能/属性后;作为使用方的订购类完全不需要去考虑在自己的内部修改代码);保证了开闭原则.

增加一个简单工厂类SimpleFactory

//使用简单工厂将创建披萨对象封装起来;
public class SimpleFactory {
    //根据披萨的种类去提供披萨的对象实例;
    public Pizza createPizza(String orderType){
        Pizza pizza=null;
        if(orderType.equals("CheesePizza")){
            pizza=new CheesePizza();
        }else if(orderType.equals("GreekPizza")){
            pizza=new GreekPizza();
        }
        return pizza;
    }
}

修改订购披萨类ToOrderPizza

//订购披萨类;
public class ToOrderPizza {
    //定义简单工厂属性;
    private SimpleFactory simpleFactory;

    Pizza pizza=null;

    //在初始化构造方法处就去设置简单工厂对象;
    public ToOrderPizza(SimpleFactory simpleFactory) {
        setSimpleFactory(simpleFactory);
    }

    //设置简单工厂对象;
    public void setSimpleFactory(SimpleFactory simpleFactory) {
        //用户输入披萨类型;
        String orderType="";
        //设置简单工厂对象;
        this.simpleFactory = simpleFactory;
        do {
            //先获取披萨种类;
            orderType = gettype();
            //调用工厂对象的方法创建披萨对象;
            pizza = this.simpleFactory.createPizza(orderType);

            if(pizza!=null){
                //披萨制作;
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }else{
                System.out.println("<----没有该种类披萨,订购失败---->");
                break;
            }
        }while (true);
    }

    //获取披萨的种类;
    private String gettype() {
        try {
            BufferedReader strs = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("输入订购的披萨种类:");
            String str = strs.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

披萨店类调用订购类时,构造方法内传入简单工厂对象;

//披萨店类;
public class PizzaShop {
    public static void main(String[] args) {
        //订购披萨;
        new ToOrderPizza(new SimpleFactory());
        System.out.println("结束");
    }
}

测试使用;

输入订购的披萨种类:
CheesePizza
奶酪披萨准备材料工作
奶酪披萨 烘焙中...;
奶酪披萨 切片中.....;
奶酪披萨 打包....;
输入订购的披萨种类:
GreekPizza
希腊披萨准备工作
希腊披萨 烘焙中...;
希腊披萨 切片中.....;
希腊披萨 打包....;
输入订购的披萨种类:
adsasdsa
<----没有该种类披萨,订购失败---->
结束

简单工厂模式,实际上也可以修改为静态工厂模式,
将简单工厂内的创建披萨对象方法设置为静态方法;
这样,在订购类中无需创建工厂对象即可调用方法;

简单静态工厂类;SimpleFactory

//使用简单工厂将创建披萨对象封装起来;
public class SimpleFactory {
    //根据披萨的种类去提供披萨的对象实例;
    public static Pizza createPizza(String orderType){
        Pizza pizza=null;
        if(orderType.equals("CheesePizza")){
            pizza=new CheesePizza();
        }else if(orderType.equals("GreekPizza")){
            pizza=new GreekPizza();
        }
        return pizza;
    }
}

订购披萨类ToOrderPizza;
自然也就不需要去定义工厂类作为属性了;直接调用方法即可.

//订购披萨类;
public class ToOrderPizza {

    Pizza pizza=null;
    //定义披萨类型;
    String orderType="";
    //在初始化构造方法;
    public ToOrderPizza() {
        do {
            //先获取披萨种类;
            orderType = gettype();
            //调用简单工厂的方法创建披萨对象;
            pizza = SimpleFactory.createPizza(orderType);
            if(pizza!=null){
                //披萨制作;
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }else{
                System.out.println("<----没有该种类披萨,订购失败---->");
                break;
            }
        }while (true);
    }

    //获取披萨的种类;
    private String gettype() {
        try {
            BufferedReader strs = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("输入订购的披萨种类:");
            String str = strs.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

披萨店类PizzaShop

//披萨店类;
public class PizzaShop {
    public static void main(String[] args) {
        //订购披萨,完成工作;
        new ToOrderPizza();
        System.out.println("结束");
    }
}

🚗工厂方法模式

这时有一个新的需求,在点披萨的时候,还要考虑产地问题;

如果说,还用简单工厂模式解决的话,此时需要创建几个不同产地的简单工厂类(每个工厂类内部决定创建什么口味的披萨实例对象);
那么只要来个订购类;他就需要去聚合;项目的耦合过高,维护性差.

那么,引入工厂方法模式;让子类决定对象的实例化

而工厂方法模式是在工厂类中定义创建不同口味披萨对象的抽象方法;
然后让不同产地的子类继承这个工厂类;
不同产地的子类在实现方法时,依赖于不同口味的披萨对象.

案例代码;
披萨类Pizza

//将披萨类定义为抽象类;
public abstract class Pizza {
    //披萨的种类名;
    protected String name;

    //制作披萨时准备原材料的工作;
    public abstract void prepare();

    //烘烤披萨;
    public void bake() {
        System.out.println(name + " 烘焙中...;");
    }

    //披萨切片;
    public void cut() {
        System.out.println(name + " 切片中.....;");
    }

    //披萨包装;
    public void box() {
        System.out.println(name + " 打包....;");
    }

    //为披萨设置种类名;
    public void setName(String name) {
        this.name = name;
    }
}

北京生产的奶酪味披萨BJChessPizza

//北京生产的的奶酪味披萨
public class BJChessPizza extends Pizza{
    @Override
    public void prepare() {
        setName("北京奶酪味披萨");
        System.out.println("北京生产的奶酪味披萨准备工作==>;");
    }
}

北京生产的胡椒味披萨BJPepperPizza

//北京生产的胡椒味披萨;
public class BJPepperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("北京胡椒味披萨");
        System.out.println("北京生产的胡椒味披萨准备工作==>;");
    }
}

伦敦生产的奶酪味披萨LDChessPizza

//伦敦生产的的奶酪味披萨
public class LDChessPizza extends Pizza{
    @Override
    public void prepare() {
        setName("伦敦奶酪味披萨");
        System.out.println("伦敦生产的奶酪味披萨准备工作==>;");
    }
}

伦敦生产的胡椒味披萨LDPepperPizza

//伦敦生产的胡椒味披萨;
public class LDPepperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("伦敦胡椒味披萨");
        System.out.println("伦敦生产的胡椒味披萨准备工作==>;");
    }
}

订购披萨类ToOrderPizza

//订购披萨类;
public abstract class ToOrderPizza {
    
    //定义根据披萨种类创建披萨对象的抽象方法
    abstract Pizza createPizza(String orderType);

    //在初始化构造方法;
    public ToOrderPizza() {
        Pizza pizza = null;
        //定义披萨类型;
        String orderType = "";
        do {
            //先获取披萨种类;
            orderType = gettype();
            //这里的方法由子类去实现;
            pizza=createPizza(orderType);
            if(pizza!=null) {
                //披萨制作;
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }else{
                System.out.println("<----没有该种类披萨,订购失败---->");
                break;
            }
        } while (true);
    }

    //获取披萨的种类;
    private String gettype() {
        try {
            BufferedReader strs = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("输入订购的披萨种类:");
            String str = strs.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

北京生产的订购披萨类BJOrderPizza

//北京产地的订购披萨;
public class BJOrderPizza extends ToOrderPizza{
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza=null;
        if(orderType.equals("chess")){
            pizza = new BJChessPizza();
        }else if(orderType.equals(深入理解设计模式-简单工厂模式(静态工厂方法模式)

GOF三种工厂模式~

设计模式之一(简单工厂模式)

设计模式工厂模式

Java设计模式学习记录-简单工厂模式工厂方法模式

3 种工厂模式详解(JS)