写点什么

设计模式 - 工厂方法模式和抽象工厂模式

作者:C++后台开发
  • 2023-02-08
    湖南
  • 本文字数:5327 字

    阅读完需:约 17 分钟

设计模式-工厂方法模式和抽象工厂模式

一. 工厂方法模式

1. 定义和特点

(1). 定义:定义一个创建产品对象的工厂接口,然后把产品对象的实际创建工作放到具体的子类工厂当中实现。


PS:


① 我们把被创建的对象成为“产品”,创建产品的对象称为“工厂”。如果创建的产品不多,且基本不会增加新产品,只需要一个工厂类即可,这种模式叫做“简单工厂”,它不属于 23 种设计模式,它的缺点是违背了开闭原则。


② 此处的介绍的‘抽象工厂’,是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。


(2). 优点:


A. 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程.


B. 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则.


(3). 缺点:


每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

2. 具体实现

(1). 模式的结构


A. 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 如: newProduct() 来创建产品。


B. 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。


C. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。


D. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。


结构图如下:



(2). 应用场景


需要画各种图,比如 Circle、Rectangle、Square,首先要有一个 Draw 方法,我们可以把它抽象成一个接口,让每个形状类去实现它;形状类的创建我们采用工厂去创建,可以先抽象出来一个工厂接口,声明创建对象的方法 CreateShape,然后让每个形状的子工厂去实现它。


如果形状有限,且不经常添加,直接创建一个简单工厂来实例化各个形状类即可。


(3). 代码实操


形状类代码:


     /// <summary>    /// 形状接口    /// </summary>    public interface IShape    {        /// <summary>        /// 画图方法        /// </summary>        public void Draw();    }    /// <summary>    /// 圆形    /// </summary>    public class Circle : IShape    {        public void Draw()        {            Console.WriteLine("画出一个圆形");        }    }     /// <summary>    /// 矩形    /// </summary>    public class Rectangle : IShape    {        public void Draw()        {            Console.WriteLine("画出一个矩形区域");        }    }     /// <summary>    /// 正方形    /// </summary>    public class Square : IShape    {        public void Draw()        {            Console.WriteLine("画出一个正方形区域");        }    }
复制代码


简单工厂代码:


    /// <summary>    /// 形状工厂类 (简单工厂)    /// </summary>    public class SimpleFactory    {        /// <summary>        /// 通过名称获取对应的形状类        /// </summary>        /// <param name="shapeType"></param>        /// <returns></returns>        public IShape getShape(String shapeType)        {            if (shapeType == null)            {                return null;            }            if (shapeType.Equals("CIRCLE"))            {                return new Circle();            }            else if (shapeType.Equals("RECTANGLE"))            {                return new Rectangle();            }            else if (shapeType.Equals("SQUARE"))            {                return new Square();            }            return null;        }    }
复制代码


工厂方法代码:


    /// <summary>    /// 抽象所有工厂的接口    /// </summary>    public interface AbstractFactory    {        //创建具体的‘对象’接口        IShape CreateShape();    }    /// <summary>    /// Circle工厂类    /// </summary>    public class CircleFactory : AbstractFactory    {        public IShape CreateShape()        {            return new Circle();        }    }    /// <summary>    /// Rectangle工厂类    /// </summary>    public class RectangleFactory : AbstractFactory    {        public IShape CreateShape()        {            return new Rectangle();        }    }    /// <summary>    /// Square工厂类    /// </summary>    public class SquareFactory : AbstractFactory    {        public IShape CreateShape()        {            return new Square();        }    }
复制代码


测试结果:


//简单工厂的实现                {                    Console.WriteLine("-------------------下面简单工厂的实现------------------------");
SimpleFactory shapeFactory = new SimpleFactory();
//获取 Circle 的对象,并调用它的 draw 方法 IShape shape1 = shapeFactory.getShape("CIRCLE"); shape1.Draw();
//获取 Rectangle 的对象,并调用它的 draw 方法 IShape shape2 = shapeFactory.getShape("RECTANGLE"); shape2.Draw();
//获取 Square 的对象,并调用它的 draw 方法 IShape shape3 = shapeFactory.getShape("SQUARE"); shape3.Draw(); }
//工厂方法的实现 { Console.WriteLine("-------------------下面工厂方法的实现------------------------");
//获取 Circle 的对象,并调用它的 draw 方法 AbstractFactory f1 = new CircleFactory(); IShape shape1 = f1.CreateShape(); shape1.Draw();
//获取 Rectangle 的对象,并调用它的 draw 方法 AbstractFactory f2 = new RectangleFactory(); IShape shape2 = f2.CreateShape(); shape2.Draw();
//获取 Square 的对象,并调用它的 draw 方法 AbstractFactory f3 = new CircleFactory(); IShape shape3 = f3.CreateShape(); shape3.Draw();
}
复制代码


运行结果:



更多 C++后台开发技术点知识内容包括 C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,音视频开发,Linux 内核,TCP/IP,协程,DPDK 多个高级知识点。


C/C++Linux服务器开发高级架构师/C++后台开发架构师免费学习地址


【文章福利】另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以点击领取



二. 抽象工厂模式

1. 背景

前面介绍【工厂方法模式】考虑的是一类产品的生产,如 形状类只画图、畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。


同种类称为同等级,也就是说:【工厂方法模式】只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如 工具类既能画图也能染色、农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。


本节要介绍的【抽象工厂模式】将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,图 1 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。


2. 定义和特点

(1) 定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。


抽象工厂需要满足下面条件:


A. 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。


B. 系统一次只可能消费其中某一族产品,即同族的产品一起使用。


(2).优点


A. 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。


B. 当增加一个新的产品族时不需要修改原代码,满足开闭原则。


(3).缺点


当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

3. 具体实现

(1). 模式的结构


抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。


A. 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。


B. 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。


C. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。


D. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。


结构图如下:


(2). 应用场景


我既要画图又要染色,且画图和染色有个对应关系:Circle 对应 Blue,Rectangle 对应 Green, 这个时候我们就要使用抽象工厂模式, 形状和颜色属于‘同族下的不同产品’,设计抽象工厂,定义创建形状和创建颜色的方法,同时设计多个子工厂,每个子工厂继承抽象工厂,并且实现属于自己的形状和颜色的创建。


(3). 代码实操


具体产品类(形状和颜色)


    /// <summary>    /// 形状接口    /// </summary>    public interface IShape2    {        /// <summary>        /// 画图方法        /// </summary>        public void Draw();    }    /// <summary>    /// 圆形    /// </summary>    public class Circle2 : IShape2    {        public void Draw()        {            Console.WriteLine("画出一个圆形");        }    }    /// <summary>    /// 矩形    /// </summary>    public class Rectangle2 : IShape2    {        public void Draw()        {            Console.WriteLine("画出一个矩形区域");        }    } /// <summary>    ///  颜色接口    /// </summary>   public interface IColor2   {       /// <summary>       /// 填充颜色方法       /// </summary>       public void Fill();   }class Blue2 : IColor2    {        public void Fill()        {            Console.WriteLine("Inside Blue:我是蓝色");        }    }class Green2 : IColor2    {        public void Fill()        {            Console.WriteLine("Inside Green:我是绿色");        }    }
复制代码


抽象工厂类和子工厂代码


   /// <summary>    /// 抽象工厂    /// 核心:在一个工厂里聚合多个同类产品。    /// (这里也可以定义成接口)    /// </summary>    public abstract class AbstractFactory2    {        public abstract IColor2 CreateColor();        public abstract IShape2 CreateShape();    }   /// <summary>    /// 工厂1    /// (用来图Blue2色 和 创建Cicle2形状)    /// </summary>   public class ConcreteFactory1 : AbstractFactory2    {        public override IColor2 CreateColor()        {            return new Blue2();        }        public override IShape2 CreateShape()        {            return new Circle2();        }    }    /// <summary>    /// 工厂2    /// (用来图Blue2色 和 创建Cicle2形状)    /// </summary>    public class ConcreteFactory2 : AbstractFactory2    {        public override IColor2 CreateColor()        {            return new Green2();        }        public override IShape2 CreateShape()        {            return new Rectangle2();        }    }
复制代码


测试代码


               //工厂1 画图并填充颜色                AbstractFactory2 f1 =new  ConcreteFactory1();                IShape2 s1 = f1.CreateShape();                IColor2 c1 = f1.CreateColor();                s1.Draw();                c1.Fill();
//工厂2 画图并填充颜色 AbstractFactory2 f2 = new ConcreteFactory2(); IShape2 s2 = f2.CreateShape(); IColor2 c2 = f2.CreateColor(); s2.Draw(); c2.Fill();
复制代码


运行结果


原文链接:https://www.cnblogs.com/yaopengfei/p/13428543.html

用户头像

C/C++后台开发技术交流qun:720209036 2022-05-06 加入

还未添加个人简介

评论

发布
暂无评论
设计模式-工厂方法模式和抽象工厂模式_数据结构_C++后台开发_InfoQ写作社区