• 设计模式----工厂方法模式


    创建型模式       

           工厂方法模式属于类的创建行模式又被称为多态工厂模式。工厂方法模式的意义在于定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中,核心工厂类将不在负责产品的创建,这昂核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。

           简单工厂模式又叫静态工厂模式,由一个工厂决定创建出哪一种商品的实例。只要输入想要的产品代号,就会实例化合适的对象。

           这里举个简单的例子就是:小张开了一家面包店,根据客人的不同需求提供不同的面包,这里就有不同的面包师傅做不同的面包,这些个面包师傅(HoneyBread、BlackBread)等又归一个总师傅管理BreadMaker,也就是这些师傅的手艺都是继承自该师傅,这个厨房后台呢,就相当于一个工厂(IFactory),不同的种类就由不同的工厂(HoneyFactory)生产,工厂会根据需求将不同的种类产品分给不同种类的总师傅(PizzaMaker、BreadMaker),在由师傅分配任务给不同的制作师。上诉流程就将整个工厂模型的思路理清了。

    简单工厂类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.hust.SimpleFactory;
     
    public class BreadFactory {
     
        public static BreadMaker MakeBread(int breadType){
     
            BreadMaker breadMaker = null;
            switch (breadType) {
            case 1:
                breadMaker = new BlackBread();
                break;
            case 2:
                breadMaker =  new HoneyBread();
                break;
            case 3:
                breadMaker =  new WhiteBread();
                break;
            default:
                break;
            }
            return breadMaker;
        }
    }

    总师傅:

    1
    2
    3
    4
    5
    6
    7
    package com.hust.SimpleFactory;
     
    public class BreadMaker {
        public void GetBread(){
            //nothing
        }
    }

    不同的面包师傅:

    1
    2
    3
    4
    5
    6
    7
    package com.hust.SimpleFactory;
     
    public class BlackBread extends BreadMaker {
        public void  GetBread() {
            System.out.println("做出黑面包");;
        }
    }
    1
    2
    3
    4
    5
    public class HoneyBread extends BreadMaker {
        public void GetBread() {
            System.out.println("做出蜂蜜面包");
        }
    }

    商店前台:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public static void main(String args[]) {
        BreadMaker breadMaker;
        System.out.println("面包店开业!");
        System.out.println("开始制作黑面包");
        breadMaker = BreadFactory.MakeBread(1);
        breadMaker.GetBread();
        System.out.println("开始制作蜂蜜面包");
        breadMaker = BreadFactory.MakeBread(2);
        breadMaker.GetBread();
        System.out.println("开始制作白面包");
        breadMaker = BreadFactory.MakeBread(3);
        breadMaker.GetBread();
    }

    工厂模式:除了上诉内容外增加了一个总工厂负责类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package com.hust.Factory;
     
    import com.hust.AbstractFactory.PizzaMaker;
    import com.hust.SimpleFactory.BreadMaker;
     
    public interface IFactory {
        BreadMaker createBread();
     
        PizzaMaker createPizza();
    }

    不同的工厂类:如果增加pizza这个产品,就在总工厂里增加一个函数负责pizza(这就是抽象工厂模式)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class HoneyFactory implements IFactory {
     
        @Override
        public BreadMaker createBread() {
            return new HoneyBread();
        }
     
        @Override
        public PizzaMaker createPizza() {
            return new HoneyPizza();
        }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class BlackFactory implements IFactory {
        @Override
        public BreadMaker createBread() {
            return new BlackBread();
        }
     
        @Override
        public PizzaMaker createPizza() {
            return new BlackPizza();
        }
     
    }

    工厂模式时的柜台操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static void main(String args[]) {
        BreadMaker breadMaker;
        System.out.println("面包店开业!");
        System.out.println("开始制作黑面包");
        IFactory breadFactory = new BlackBreadFactory();
        breadMaker = breadFactory.createBread();
        breadMaker.GetBread();
        System.out.println("开始制作蜂蜜面包");
        breadFactory = new HoneyBreadFactory();
        breadMaker = breadFactory.createBread();
        breadMaker.GetBread();
        system.out.println("开始制作蜂蜜pizza");
            breadFactory = new HoneyBreadFactory();
        PizzaMaker pizzaMaker = breadFactory.createPizza();
        pizzaMaker.GetPizza();
    }

    不同的产品的师傅:

    1
    2
    3
    4
    5
    public class PizzaMaker {
        public void  GetPizza() {
            //nothing
        }
    }
    1
    2
    3
    4
    5
    6
    7
    public class HoneyPizza extends PizzaMaker {
        @Override
        public void GetPizza() {
            // TODO Auto-generated method stub
            System.out.println("做出蜂蜜披萨");
        }
    }

    关于面包店的总结构图如下:

    问题:假设小张有很多分店,每个分店有不同的柜台,那天小张决定将黑巧克力面包改成抹牛油的,在修改了工厂之后,必须相应的修改柜台的代码,级每一个申明过breadMaker和pizzaMaker的地方都要修改,那么工作量将恨大。这就体现了抽象模式的缺点,便于交换产品的同时,也需要改动产品声明过的地方。如何避免呢?一种方法就是根据前台用户的输入,使用if switch语句进行判断,但随着产品的增长,分支会越来越多。那么客户端还是需要大量的修改。另一种方法就是——反射。对客户端代码修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    try {
                Class<?> c = Class.forName("HoneyBreadFactory");
                try {
                    breadFactory = (IFactory) c.newInstance();
                    pizzaMaker = breadFactory.createPizza();
                    pizzaMaker.GetPizza();
                catch (Exception e) {
                    // TODO: handle exception
                }
            catch (ClassNotFoundException e) {
                // TODO: handle exception
            }

    这样就避免了分支的出现。

    这里提到了三个工厂模式:简单工厂、工厂方法、抽象工厂。他们的优缺点如下:

      简单工厂 工厂方法 抽象工厂
    优点

    1、分离了客户端和后台逻辑,使得客户端无需关心后台的实现,去除了客户端与具体产品的分离,增强了移植性。

    2、实现简单

    1、易于添加新产品

    2、后台模块契合了开放-封闭原则

    1、分离了具体的类,客户端通过抽象接口操纵实例,

    2、易于交换产品系列

    3、有利于产品的一致性,一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用一列中的对象。

    缺点

    1、违背了开放封闭原则

    2、添加新产品时比较麻烦

    1、新产品的添加带来了大量类的创建,增加了工作量

    2、客户端仍然违反开放封闭原则,只是后台逻辑判断挪到了前台

    1、难以支持新种类的产品,抽象接口确定了可以被创建的产品集合。新种类产品加入需要扩展接口,这就涉及到接口本身和所有的实现类的改变。

  • 相关阅读:
    docker6 管理工具
    docker1 初识docker
    libsvm处理多分类的问题
    selenium webdriver 的三种等待方式
    文本深度表示模型Word2Vec
    机器学习中训练集、验证集、测试集的定义和作用
    机器学习中防止过拟合的处理方法
    用Python读取大文件
    进化世界
    EDS(实例)
  • 原文地址:https://www.cnblogs.com/silence-hust/p/4125679.html
Copyright © 2020-2023  润新知