热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计方法之-抽象工厂(AbstractFactory)

设计方法之-抽象工厂(AbstractFactory)
  • 常规的对象创建方法:

    //创建一个Road对象
    Road road =new Road();


    new
    的问题:
       
    实现依赖,不能应对具体实例化类型的变化。
    解决思路:
       
    封装变化点-----哪里变化,封装哪里
       
    潜台词: 如果没有变化,当然不需要额外的封装!

    工厂模式的缘起
       
    变化点在对象创建,因此就封装对象创建
       
    面向接口编程----依赖接口,而非依赖实现
    最简单的解决方法:

    1 class RoadFactory{
    2 public static Road CreateRoad()
    3 {                                
    4   return new Road();   
    5 }
    6 }
    7 //
    创建一个Road对象
    8 Road road=roadFactory.CreateRoad();

    创建一系列相互依赖对象的创建工作:
    假设一个游戏开场景:
    我们需要构造"道路""房屋""地道""从林"...等等对象
    工厂方法如下:

     1     class RoadFactory
     2     {
     3         public static Road CreateRoad()
     4         {
     5             return new Road();
     6         }
     7         public static Building CreateBuilding()
     8         {
     9             return new Building();
    10         }
    11         public static Tunnel CreateTunnel()
    12         {
    13             return new Tunnel();
    14         }
    15         public static Jungle CreateJungle()
    16         {
    17             return new Jungle();
    18         }
    19     }

    调用方式如下:

    1         Road road =  RoadFactory.CreateRoad();
    3         Building building = RoadFactory.CreateBuilding();
    4         Tunnel tunnel = RoadFactory.CreateTunnel();
    5         Jungle jungle = RoadFactory.CreateJungle();

    如上可见简单工厂的问题:
       
    不能应对"不同系列对象"的变化。比如有不同风格的场景---对应不同风格的道路,房屋、地道....

    如何解决:
       
    使用面向对象的技术来"封装"变化点。
    动机(Motivate)
       
    在软件系统中,经常面临着"一系统相互依赖的对象"的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作。
       
    如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种"封装机制"来避免客户程序和这种"多系列具体对象创建工作"的紧耦合?

    意图(Intent):
        提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
                                                     ----
    《设计模式》GOF
    结构图(Struct):
               

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    适用性:
       
    1.一个系统要独立于它的产品的创建、组合和表示时。
        2.
    一个系统要由多个产品系统中的一个来配置时。
        3.
    当你要强调一系列相关的产品对象的设计以便进行联合使用时。
        4.
    当你提供一个产品类库,而只想显示它们的接口不是实现时。
    生活例子:

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    结构图代码实现:

    1  abstract class AbstractFactory
    2     {
    3        public abstract AbstractProductA CreateProductA();
    4        public abstract AbstractProductB CreateProductB();
    5     }

     

    1   abstract class AbstractProductA
    2     {
    3        public abstract void Interact(AbstractProductB b);
    4     }

     

    1   abstract class AbstractProductB
    2     {
    3        public abstract void Interact(AbstractProductA a);
    4     }

     

     1    class Client
     2     {
     3         private AbstractProductA AbstractProductA;
     4         private AbstractProductB AbstractProductB;
     5         public Client(AbstractFactory factory)
     6         {
     7             AbstractProductA = factory.CreateProductA();
     8             AbstractProductB = factory.CreateProductB();           
     9         }
    10         public void Run()
    11         {
    12             AbstractProductB.Interact(AbstractProductA);
    13             AbstractProductA.Interact(AbstractProductB);
    14         }
    15     }

     1  class ConcreteFactory1:AbstractFactory
     2     {
     3         public override AbstractProductA CreateProductA()
     4         {
     5             return new ProductA1();
     6         }
     7         public override AbstractProductB CreateProductB()
     8         {
     9             return new ProductB1();
    10         }
    11     }

     1     class ConcreteFactory2:AbstractFactory
     2     {
     3         public override AbstractProductA CreateProductA()
     4         {
     5             return new ProdcutA2();
     6         }
     7         public override AbstractProductB CreateProductB()
     8         {
     9             return new ProductB2();
    10         }
    11     }

    1  class ProductA1:AbstractProductA
    2     {
    3         public override void Interact(AbstractProductB b)
    4         {
    5             Console.WriteLine(this.GetType().Name + "interact with" + b.GetType().Name);
    6         }
    7     }

    1   class ProductB1:AbstractProductB
    2     {
    3         public override void Interact(AbstractProductA a)
    4         {
    5             Console.WriteLine(this.GetType().Name + "interact with" + a.GetType().Name);
    6         }
    7     }

    1   class ProdcutA2:AbstractProductA
    2     {
    3         public override void Interact(AbstractProductB b)
    4         {
    5             Console.WriteLine(this.GetType().Name + "interact with" + b.GetType().Name);
    6         }
    7     }

    1  class ProductB2:AbstractProductB
    2     {
    3         public override void Interact(AbstractProductA a)
    4         {
    5             Console.WriteLine(this.GetType().Name + "interact with" + a.GetType().Name);
    6         }
    7     }

     1    public static void Main()
     2         {
     3          // Abstractfactory1
     4             AbstractFactory factory1 = new ConcreteFactory1();
     5             Client c1 = new Client(factory1);
     6             c1.Run();
     7         // Abstractfactory2
     8             AbstractFactory factory2 = new ConcreteFactory2();
     9             Client c2 = new Client(factory2);
    10             c2.Run();
    11         }

     

    Abstract Factory注意的几点:
        如果不存在多系列对象创建的需求变化,则没必要应用Abstract Factory模式,静态工厂方法足矣。
        "
    系列对象"指的是这些对象之间有相互依赖、或作用的关系。例如游戏开发场景中的"道路""房屋"依赖,道路地道的依赖。
    Abstract Factory
    模式主要在于应对"新系列"的需求变动。其缺点在于难以应对新对象的需求变动。
    Abstract Factory
    模式经常和Factory Method模式共同组合来应对对象创建的需求变化。


  • 推荐阅读
    • 深入解析JVM垃圾收集器
      本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
    • 非公版RTX 3080显卡的革新与亮点
      本文深入探讨了图形显卡的进化历程,重点介绍了非公版RTX 3080显卡的技术特点和创新设计。 ... [详细]
    • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
    • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
    • 在 Windows 10 中,F1 至 F12 键默认设置为快捷功能键。本文将介绍几种有效方法来禁用这些快捷键,并恢复其标准功能键的作用。请注意,部分笔记本电脑的快捷键可能无法完全关闭。 ... [详细]
    • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
      来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
    • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
    • 技术分享:从动态网站提取站点密钥的解决方案
      本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
    • 计算机网络复习:第五章 网络层控制平面
      本文探讨了网络层的控制平面,包括转发和路由选择的基本原理。转发在数据平面上实现,通过配置路由器中的转发表完成;而路由选择则在控制平面上进行,涉及路由器中路由表的配置与更新。此外,文章还介绍了ICMP协议、两种控制平面的实现方法、路由选择算法及其分类等内容。 ... [详细]
    • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
    • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
    • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
    • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
    • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
    • 本文介绍了在使用Visual Studio 2015进行项目开发时,遇到类向导弹出“异常来自 HRESULT:0x8CE0000B”错误的解决方案。通过具体步骤和实践经验,帮助开发者快速排查并解决问题。 ... [详细]
    author-avatar
    freezing-wing
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有