zoukankan      html  css  js  c++  java
  • 浅谈简单工厂,工厂方法,抽象工厂的区别和使用

      工厂模式是分为三种,分别是简单工厂,工厂方法,抽象工厂。其中工厂方法和抽象工厂是GoF23种设计模式中的一种,而简单工厂则不是一种设计模式,更加可以理解的是一种编码时候预定俗称的一种习惯。那么,就在接下来三点中分别去分析理解工厂模式。

    一 简单工厂:通过实例化一个工厂类,来获取对应的产品实例。我们不需要关注产品本身如何被创建的细节,只需要通过相应的工厂就可以获得相应的实例。简单工厂包括三种角色:

    1.工厂:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。  

    2.抽象产品 :简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

    3.具体产品:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

    比如以下例子:

            

                                (类设计的UML图) 

    1.Drinks作为产品的抽象类并且有抽象方法produce();(抽象产品
    public  abstract class Drinks {    
      protected abstract void produce();
    }
    2.Sprite继承Drinks是要被具体生产出来的产品,他重写了produce()方法。(具体产品)
    public class Sprite extends Drinks {

    @Override
    protected void produce() {
    System.out.println("drink sprite");
    }
    }

    3.Cola同样也继承了Drinks,是要被生产出来的具体产品。
    (具体产品)
    public class Cola extends Drinks {

    @Override
    protected void produce() {
    System.out.println("Drink Cola");
    }
    }

    4.DrinksFactory为简单工厂,向外暴露produceDrink方法来获取产品的实例(工厂
    public class DrinksFactory {

    public Drinks produceDrink(Class className){
    try {
    return (Drinks) Class.forName(className.getName()).newInstance();
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }

    return null;
    }
    }

    5.Client为应用层,Client端想要获取到Cola或者Sprite对象,只要通过DrinkFactory中的produceDrink方法传入相对应的对应的产品
    public class Client {
    public static void main(String[] args) {
    DrinksFactory factory = new DrinksFactory();
    Cola cola = (Cola) factory.produceDrink(Cola.class);
    cola.produce();
    }
    }
    简单工厂的优点:
    1.不需要关心类的创建细节。
    2.减轻类之间的耦合依赖,具体类的实现只是依赖于简单工厂,而不依赖其他类。

    简单工厂的缺点:
    1.扩展复杂,当简单工厂需要生产出另外一种产品的时候,需要扩展工厂的内部创建逻辑,比较有可能引起较大的故障
    2.由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中


    二.工厂方法

      工厂方法的定义是:定义一个创建对象的接口,让实现这个接口的的类去决定实例化具体的类。工厂方法让类的实例化推迟到实现接口的子类中进行。

      比如说,我现在需要一瓶可乐,有可口可乐公司生产的可乐也有百事可乐公司生产的可乐,那么对于可乐这个产品等级(抽象工厂中会具体说明),具体生产什么可乐并不是在一个工厂实现,而是由一个可乐工厂指定一个标准(接口里面的抽象方法),可口可乐公司百事可乐公司只要按照这个标准去生产就可以了。   

                                                   

                                                 (2)工厂方法的Uml类图 

    1.Cola此类是产品的父类
    public abstract class Cola {
    protected abstract void drinks();
    }
    2.PepsiCola继承Cola,是要生产的产品之一
    public class PepsiCola extends  Cola {

    @Override
    protected void drinks() {
    System.out.println("Drinks PepsiCola");
    }
    }
    3.CoCoCola同样继承Cola,也是要生产的产品之一
    public class CoCoCola extends Cola {

    @Override
    protected void drinks() {
    System.out.println("Drinks cococoLa");
    }
    }
    4.ColaFacotry定义抽象工厂,指定要生产此类产品的规范(存在的方法与属性),指定工厂方法
    public interface ColaFacotry {

    Cola produce(Class<Cola> cola);
    }
    5.PepsiColaFactory定义子类工厂,它继承抽象工厂,实现了对某一产品等级的产品的获得
    public class PepsiColaFactory implements ColaFacotry {

    public PepsiCola produce(Class cola) {
    if (cola.isInstance(PepsiCola.class)){
    return new PepsiCola();
    }
    return null;
    }
    }
    6.ColaFacotry,是规定工厂方法去获得拿一些的产品等级的商品,比如说,我规定生产的产品等级是可乐和草莓可乐,那么对于它的实现类来说,也就是其子类中的重载方法来说去具体实现获取产品的具体实现。
    public interface ColaFacotry {

    Cola produce(Class<Cola> cola);
    }



    三.抽象工厂

      抽象工厂是提供了创建一系列服务的的对象的接口。那么问题就来了,怎么区分和工厂方法中的服务对象宁?此时就需要对一组概念有所理解,即产品等级和产品族,我从网上找到下面这张图,进行解释说明。在图(4)中,我们可以通过横向和纵向的比较,横向是某一个手机厂商如苹果,小米等,他们不仅仅生产手机,还生产电脑,耳机等一系类产品,那么我们把苹果,小米,华为这样的厂商可以认为他们生产的是一个产品族,而他们自己本身就是一个抽象工厂的具体实现;那么纵向来看,不管是小米华为还是苹果,他们生产的产品是按照一定的规则来生产,显示屏,电池,处理器等等,所以对于纵向的产品来说,他们又是属于同一个产品等级,我们亦可以称他们的实现为工厂方法。

      综上所述,抽象工厂解决的是横向的产品族,工厂方法解决的是纵向的产品等级。具体抽象工厂请看代码。

                     

                                                  (3)产品等级和产品族(图片来自https://laravel-china.org/topics/18598?order_by=created_at&) 

                              

                              (4)产品等级示意图

       1.AbstractFactory 抽象工厂

    public  interface AbstractFactory {

    public Phone producePhone();

    public Computer producaComputer();
    }
    2.AppleFactory具体工厂的实现一
    public class AppleFactory implements AbstractFactory {
    public Phone producePhone() {
    return new Iphone();
    }

    public Computer producaComputer() {
    return new Mac();
    }
    }
    3.MiFactory具体工厂的实现二
    public class MiFactory implements AbstractFactory {
    public Phone producePhone() {
    return new MiPhone();
    }

    public Computer producaComputer() {
    return new MiComputer();
    }
    }
    4.Phone抽象产品等级一
    public abstract class Phone {
    public abstract void call();
    }
    5.Iphone具体产品一
    public class Iphone extends Phone {

    @Override
    public void call() {
    System.out.println("Iphone call");
    }
    }
    6.MiPhone具体产品一
    public class MiPhone extends Phone {

    @Override
    public void call() {
    System.out.println("Mi Phone call");
    }
    }
    7.Computer抽象产品等级二
    public  abstract class Computer {

    public abstract void work();
    }
    8.Mac具体产品一
    public class Mac extends Computer {

    @Override
    public void work() {
    System.out.println("MAC work");
    }
    }
    9.MiComputer 具体产品二

    public class MiComputer extends Computer {

    @Override
    public void work() {
    System.out.println("MI computer word");
    }
    }
    10.客户端
    public class Clint {

    public static void main(String[] args) {
    AppleFactory appleFactory = new AppleFactory();
    appleFactory.producaComputer().work();
    appleFactory.producePhone().call();

    MiFactory miFactory = new MiFactory();
    miFactory.producaComputer().work();
    miFactory.producePhone().call();
    }
    }

          

                            (5)抽象工厂UML类图

    从UML类图中不难看出,我们如果需要拓展抽象工厂里面的方法会比较麻烦,因为我们必须修改抽象类以及添加对应的产品等级,这样修改量比较大,但是每种产品之间相互解耦,符合程序设计的“高内聚低耦合”的思想。

    最后,不管是抽象工厂还是工厂方法甚至是简单工厂,他们的存在都有一定的优缺点,在设计程序的时候要根据具体情况进行取舍,不存在那种设计好那种设计特别差,只是针对不同的业务场景的不一样的处理。

  • 相关阅读:
    vbox增加磁盘
    PMP第五版第一次考试相关提醒
    PMP学习系列7:PMBOK(5th)第五章:项目范围管理
    PMP学习系列6:PMBOK(5th)第四章-项目整合管理
    Readlist & AIM1
    如何高校管理你的时间
    PMP学习系列5:PMBOK(5th)第三章-项目管理过程
    PMP学习系列4:PMBOK(5th)第二章-组织影响和项目生命周期
    沃顿商学院最受欢迎的谈判课
    PMP学习系列3:PMBOK(5th)第一章-引言
  • 原文地址:https://www.cnblogs.com/gclokok/p/10029088.html
Copyright © 2011-2022 走看看