zoukankan      html  css  js  c++  java
  • 设计模式(二)------ 工厂模式

    一、工厂模式简介

    (1)分类

         简单工厂模式(静态工厂模式):用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码)
      工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)
      抽象工厂模式:用来生产不同产品族的固定产品(对于增加新的产品,无能为力,支持增加产品族)

    (2)核心本质:实例化对象,用工厂方法代替new操作;选择实现类、创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。

    (3)面向对象设计的基本原则:

      OCP(开闭原则):一个软件的实体应当对扩展开放,对修改关闭。

      DIP(依赖倒转原则):要针对接口编程,不要针对实现编程。

      LOD(迪米特法则):只与你直接的朋友通信,而避免和陌生人通信。

    二、工厂模式

    1、简单工厂模式(静态工厂模式)

    public interface Car
    {
        public void run();
    }
    
    public class Byd implements Car
    {
        @Override
        public void run()
        {
            System.out.println("Byd在跑.");
        }
    }
    
    public interface Car
    {
        public void run();
    }
    
    /**
     * 简单工厂类(方式一),通过接收到参数的不同来返回不同对象的实例
     */
    public class CarFactory1
    {
        public static Car createCar(String type)
        {
            if("Audi".equals(type))
            {
                return new Audi();
            }
            else if ("Byd".equals(type))
            {
                return new Byd();
            }
            else
            {
                return null;
            }
        }
    }
    
    /**
     * 简单工厂类(方式二)
     */
    public class CarFactory2
    {
        public static Car createAudi()
        {
            return new Audi();
        }
    
        public static Car createByd()
        {
            return new Byd();
        }
    }

    以上代码的类图,如下:

            

    简单工厂实现方式有以上两种,对于增加产品,不修改代码会无能为力,违反了开闭原则。

    public class Main01
    {
        public static void main(String[] args)
        {
    // 使用简单工厂类实现的方式一 Car car1
    = CarFactory1.createCar("Audi"); car1.run(); Car car2 = CarFactory1.createCar("Byd"); car2.run(); } }

     

     2、工厂方法模式

      为了避免简单工厂模式的缺点,不完全满足OCP,使用工厂方法模式解决。

      工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个工厂类(对于一个独立模块而言),而工厂方法模式有一组实现了相同接口的工厂类。

     (1)工厂方法模式实现

    public interface Car
    {
        public void run();
    }
    
    public class Audi implements Car
    {
        @Override
        public void run()
        {
            System.out.println("Audi在跑.");
        }
    }
    
    public class Byd implements Car
    {
        @Override
        public void run()
        {
            System.out.println("Byd在跑.");
        }
    }
    
    //-------------------------------------------------------------
    
    public interface CarFactory
    {
        public Car createCar();
    }
    
    public class AudiFactory implements CarFactory
    {
        @Override
        public Car createCar()
        {
            return new Audi();
        }
    }
    
    public class BydFactory implements CarFactory
    {
        @Override
        public Car createCar()
        {
            return new Byd();
        }
    }

    (2)工厂方法模式的类图,如下:

    (3)简单工厂模式和工厂方法模式的PK

    I. 结构复杂度
      这个角度简单工厂模式占优,简单工厂模式只需要一个工厂类,而工厂方法模式的工厂类随着产品的增加而增加,会使类越来越多,从而增加结构的复杂程度。

    II. 代码复杂度
      代码复杂和结构复杂度是一对矛盾。简单工厂模式在结构方面简洁,它在代码方面肯定比工厂方法模式复杂。简单工厂模式的工厂类随着产品的增加需要增加很多方法,而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。
    III. 客户端编程难度
      工厂方法模式虽然在工厂类结构中引入了接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是一个静态类,在客户端无需实例化,这无疑很吸引人。
    IIII. 管理上难度
      虽然工厂方法模式满足OCP,有良好的扩展性;但是简单工厂模式只需要修改很少量的代码就可以满足扩展性的要求,尽管它不满足OCP,但我们不要太拘泥于设计理论。
      从维护的角度来看,若需要修改多个产品类,很可能需要修改对应的工厂类,对于工厂方法模式来说相当的麻烦,需要修改多个工厂类,而简单工厂模式只需要修改一个工厂类。

    根据设计理论建议:工厂方法模式。但实际中,我们一般使用简单工厂模式。

    3、抽象工厂模式

      用来生产不同产品族的全部产品。(对于增加新的产品,无能为力,支持增加产品族

      抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象时一种非常好的解决方式。

    (1)

     a.  发动机的接口及实现类

    public interface Engine
    {
        void run();
        void start();
    }
    
    // 高端发动机
    class EngineHigh implements Engine
    {
        @Override
        public void run()
        {
            System.out.println("发动机转的快.");
        }
    
        @Override
        public void start()
        {
            System.out.println("发动机启动快, 可以自动启停.");
        }
    }
    
    // 低端发动机
    public class EngineLow implements Engine
    {
        @Override
        public void run()
        {
            System.out.println("发动机转的慢.");
        }
    
        @Override
        public void start()
        {
            System.out.println("发动机启动慢, 不可以自动启停.");
        }
    }

    b. 座椅接口

    public interface Seat
    {
        void massge();
    }
    
    // 高端座椅
    public class SeatHigh implements Seat
    {
        @Override
        public void massge()
        {
            System.out.println("座椅按摩舒服.");
        }
    }
    
    //低端座椅
    public class SeatLow  implements Seat
    {
        @Override
        public void massge()
        {
            System.out.println("座椅没有按摩功能.");
        }
    }

    c. 高端车工厂类

    public class HighCarFactory implements CarFactory
    {
        @Override
        public Engine createEngine()
        {
            return new EngineHigh();
        }
    
        @Override
        public Seat createSeat()
        {
            return new SeatHigh();
        }
    }

    d. 低端车工厂类

    public class LowCarFactory implements CarFactory
    {
        @Override
        public Engine createEngine()
        {
            return new EngineLow();
        }
    
        @Override
        public Seat createSeat()
        {
            return new SeatLow();
        }
    }

    e. 车工厂

    public interface CarFactory
    {
        Engine createEngine();
        Seat createSeat();
    }

    f. 客户端

    public class Client
    {
        public static void main(String[] args)
        {
            CarFactory carFactory = new HighCarFactory();
    
            Engine engine = carFactory.createEngine();
            engine.run();
            engine.start();
    
            Seat seat = carFactory.createSeat();
            seat.massge();
        }
    }

    (2)类图如下:

  • 相关阅读:
    无法识别的属性“targetFramework”的解决方法
    你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧(转)
    win7系统如何安装SQL Server 2005
    2017年需要知道的技术
    平时对Vue的总结
    用rem实现h5页面的编写
    判断页面是横屏还是竖屏
    页面中插入视频兼容ie8以上的浏览器
    jquery实现加载更多效果
    联动选择通过ajax获取选择对应的数据
  • 原文地址:https://www.cnblogs.com/yufeng218/p/9278282.html
Copyright © 2011-2022 走看看