设计模式--工厂模式

在最初的学习过程中对把简单的东西搞得复杂的现象很不理解,随着经验的增长,慢慢发现我所理解的“简单”其实是针对设计的简单,这种代码缺少灵活性,目的仅仅是为了解决现有问题。而“复杂”恰恰是针对一类问题的万能方案,他可以让代码变得优雅,灵活不再是一个臃肿的胖子。

在对模式的学习过程中很容易误入歧途,陷入形式主义,对模式细节的过多关注恰恰使我们越陷越深,子曾经曰过:“学而不思则罔”,文档中的类图和实现代码往往并不能代表模式的全部,我们学习模式的重点要放在模式的意图上。

设计模式代表了最佳的实践,是开发人员在开发过程中面临一般问题的解决方案,是众多前辈们在经过相当长一段时间的试验和错误中总结出来的。

什么是设计模式

设计模式:是一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结。

使用设计模式的目的

使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码的可靠性。

设计模式的分类
设计模式--工厂模式_第1张图片
设计模式的分类
  • 创建型模式:创建型模式涉及对象的实例化,用于解耦对象的实例化过程,不让用户代码依赖于对象的创建或排列方式,避免用户直接使用new创建对象。。
  • 结构型模式:把类或对象结合在一起形成一个更大的结构,和类有关的结构型模式涉及如何合理使用继承机制;和对象有关的结构型模式涉及如何合理的使用对象组合机制。。
  • 行为型模式: 行为型模式涉及怎样合理的设计对象之间的交互通信,以及怎样合理为对象分配职责,让设计富有弹性,易维护,易复用。
工厂模式

意图:定义一个创建对象的接口。让其子类决定实例化哪一个类。使其实例化过程延迟到子类进行。

工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

三个工厂
  • 简单工厂模式

简单工厂模式又叫静态工厂方法模式,实际不能算作一种设计模式。

GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。

意图:定义一个用于创建对象的接口

具体实现:
抽象一个产品基类,(接口也可以)

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:产品的抽象类
 */
public abstract class Coffee {

    /**
     * 展示产品详情
     */
    public abstract void details();
}

产品的具体实现

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description: 美式咖啡
 */
public class Americano extends Coffee {

    @Override
    public void details() {
        System.out.print("美式咖啡,不便宜");
    }
}
/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:拿铁咖啡
 */
public class Latte extends Coffee {

    @Override
    public void details() {
        System.out.print("拿铁咖啡,不便宜");
    }
}
/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:雀巢咖啡
 */
public class Nescafe extends Coffee {

    @Override
    public void details() {
        System.out.print("雀巢咖啡,喝得起");
    }
}

简单工厂来创建不同类型的咖啡实例

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description: 简单工厂
 */
public class SimpleFactory {

    /**
     * 通过传递过来的类型创建不同实例
     * @param type
     * @return
     */
    public static Coffee createInstance(String type) {
        if (type.equals("Americano")) {
            return new Americano();
        } else if (type.equals("Latte")) {
            return new Latte();
        } else if (type.equals("Nescafe")) {
            return new Nescafe();
        } else {
            throw new RuntimeException("没有匹配到可实例化[" + type + "]对象");
        }
    }
    
}

使用

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        Coffee latte = SimpleFactory.createInstance("Latte");
        latte.details();
        Coffee americano = SimpleFactory.createInstance("Americano");
        americano.details();
        Coffee nescafe = SimpleFactory.createInstance("Nescafe");
        nescafe.details();
    }

}

简单工厂模式在实际使用过程中,对产品部分来说是符合开闭原则的,但是对于工厂部分,每增加一个新产品,都要在工厂类中增加相应的创建逻辑,这显然违背了开闭原则。

不知道设计模式六大原则的同学请自行补课
http://www.runoob.com/design-pattern/design-pattern-intro.html

  • 工厂方法模式

意图:提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。

可以理解为不同地区只生产自己类型的咖啡,美国America只生产Americano,德国Germany只生产Latte和Nescafe。
具体实现:
产品基类及实现同上
定义一个工厂基类,(使用接口的方式会更好)

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:定义一个抽象咖啡工厂
 */
public abstract class CoffeeFactory {

    /**
     * 用于生产咖啡
     * @return
     */
    public abstract Coffee createCoffee(String type);
}

咖啡工厂的具体实现

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:美国咖啡工厂
 */
public class AmericaCoffeeFactory extends CoffeeFactory{

    @Override
    public Coffee createCoffee(String type) {
        return new Americano();
    }
}
/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:德国咖啡工厂
 */
public class GermanyCoffeeFactory extends CoffeeFactory {

    @Override
    public Coffee createCoffee(String type) {
        if (type.equals("Latte")) {
            return new Latte();
        } else if (type.equals("Nescafe")) {
            return new Nescafe();
        } else {
            throw new RuntimeException("没有匹配到可实例化[" + type + "]对象");
        }
    }
}

使用

public class Test {

    public static void main(String[] args) {
        /**
         * 工厂方法模式的使用方法
         */
        CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
        Coffee americaCoffees = americaCoffeeFactory.createCoffee("");
        americaCoffees.details();

        CoffeeFactory germanyCoffeeFactory = new GermanyCoffeeFactory();
        Coffee latteCoffees = germanyCoffeeFactory.createCoffee("Latte");
        latteCoffees.details();
        Coffee nescafeCoffees = germanyCoffeeFactory.createCoffee("Nescafe");
        nescafeCoffees.details();
    }
}

工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。但是由于每新增一个新产品时就需要增加两个类,这样势必会导致系统的复杂度增加。

  • 抽象工厂模式

场景:当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。

意图:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。抽象工厂为不同产品族的对象创建提供接口。
关键点在于如何在一个工厂里聚合多个同类产品。
具体实现:
抽象出饮料制造工厂

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:
 */
public interface AbstractDrinksFactory {

    /**
     * 制造咖啡
     * @return
     */
    Coffee createCoffee();

    /**
     * 制造碳酸饮料
     * @return
     */
    Sodas createSodas();

    /**
     * 制造茶
     * @return
     */
    Tea createTea();
}

饮料工厂的具体实现

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:美国饮料工厂
 */
public class AmericaDrinksFactory implements AbstractDrinksFactory{

    @Override
    public Coffee createCoffee() {
        return new Latte();
    }

    @Override
    public Sodas createSodas() {
        return new CocaCola();
    }

    @Override
    public Tea createTea() {
        return null;
    }
}
/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:中国饮料工厂
 */
public class ChinaDrinksFactory implements AbstractDrinksFactory{

    @Override
    public Coffee createCoffee() {
        return new Latte();
    }

    @Override
    public Sodas createSodas() {
        return new CocaCola();
    }

    @Override
    public Tea createTea() {
        return new Dragon_Well();
    }
}

使用

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/10/24
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        /**
         * 抽象工厂测试
         */
        AbstractDrinksFactory chinaDrinksFactory = new ChinaDrinksFactory();
        Coffee coffee = chinaDrinksFactory.createCoffee();
        Sodas sodas = chinaDrinksFactory.createSodas();
        Tea tea = chinaDrinksFactory.createTea();
       if (coffee != null) {
            coffee.details();
        }
        if (sodas != null) {
            sodas.details();
        }
        if (tea != null) {
            tea.details();
        }
    }
}

抽象工厂模式最主要的优点就是可以在类的内部对产品族进行约束,而不必专门引入一个新的类来进行管理。
当然抽象工厂模式的缺点也非常明显,那就是产品族的不易扩展,使产品族中每需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

参考文章:
http://www.runoob.com/design-pattern/abstract-factory-pattern.html
https://www.cnblogs.com/zailushang1996/p/8601808.html
https://www.cnblogs.com/carryjack/p/7709861.html

你可能感兴趣的:(设计模式--工厂模式)