• 友链

  • 首页

  • 文章归档
h u a n b l o g
h u a n b l o g

欢

HI,Friend

04月
23
C#
设计模式

设计模式-工厂模式

发表于 2022-04-23 • 字数统计 8024 • 被 1,622 人看爆

简单工厂模式

定义

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
创建实例的方法通常是静态方法

举例

假设有个一个水果农场(工厂),生成多种水果(产品),用户需要购买水果时,只需要告诉农场需要什么水果,农场就会返回需要的水果,而无需一一寻找所需要的水果,这一步农场帮我们完成了

结构

工厂模式结构图.png

  • Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公共方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂
  • ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
  • Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象,返回所需的产品对象

实现

abstract class Product
{
    public void MethodSame()
    {
        //公共方法的实现
    }

    //声明抽象方法
    public abstract void MethodDoff();
}

class ConcretProductA : Product
{
    public override void MethodDoff()
    {
        //业务方法的实现
    }
}

class ConcretProductB : Product
{
    public override void MethodDoff()
    {
        //业务方法的实现
    }
}


class Factory
{
    //静态工厂方法
    public static Product GetProduct(string arg)
    {
        Product product = null;
        switch(arg)
        {
            case "A":
                product = new ConcretProductA();
                break;
            case "B":
                product = new ConcretProductB();
                break;
        }

        return product;


    }
}

class Program
{
    static void Main(string[] args)
    {
        Product product;
        product = Factory.GetProduct("A");
        product.MethodSame();
        product.MethodDoff();
    }
}

简化

可以将抽象产品类(Product)和工厂类(Factory)合并,将静态工厂方法移到抽象产品类中,可以通过调用产品父类的静态工厂方法,根据不同参数创建不同类型的产品子类对象

工厂模式结构图简化.png

优点

  • (1)工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费"产品,简单工厂模式实现了对象创建和使用的分离。
  • (2)客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度上减少使用者的记忆量。

缺点

  • (1)由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
  • (2)使用简单工厂模式势必会增加系统中类的个数(引人了新的工厂类),增加了系统的复杂度和理解难度。
  • (3)系统扩展困难,一旦添加新产品不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
  • (4)简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。在C#语言中,不能通过类的实例对象来访问静态方法和静态变量,无法在客户端代码中针对工厂父类编程,而在运行时使用工厂子类对象来覆盖父类,因此,工厂类不能得到很好地扩展。

适用华环境

  • (1)工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑过于复杂。
  • (2)客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

工厂方法模式

工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时还弥补了简单工厂模式的缺陷,更好地符合开闭原则的要求,在增加新的具体产品对象时不需要对已有系统做任何修改。

定义

定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。
工厂方法模式让一个类的实例化延迟到其子类。

在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

结构

工厂方法模式结构.png

  • (1)Product(抽象产品):它是定义产品的抽象类﹐是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
  • (2)ConcreteProductA/B(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
  • (3)Factory(抽象工厂):抽象工厂接口,声明了工厂方法,用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
  • (4)ConcreteFactory(具体工厂):抽象工厂接口,实现了在抽象工厂中声明的工厂方法,由客户端调用,返回一个具体产品类的实例。

实现

abstract class Product
{
    public void MethodSame()
    {
        //公共方法的实现
    }

    //声明抽象方法
    public abstract void MethodDoff();
}

//抽象工厂
interface IFactory
{
    Product FactoryMethod();
}

//工厂A类
class ConcretFactoryA : IFactory
{
    public Product FactoryMethod()
    {
        return new ConcretProductA();
    }
}

//实现类A
class ConcretProductA : Product
{
    public override void MethodDoff()
    {
        //业务方法的实现
    }
}

//工厂B类
class ConcretFactoryB : IFactory
{
    public Product FactoryMethod()
    {
        return new ConcretProductB();
    }
}

//实现类B
class ConcretProductB : Product
{
    public override void MethodDoff()
    {
        //业务方法的实现
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFactory factory;
        factory = new ConcretFactoryA();
        Product product;
        product = factory.FactoryMethod();
    }
}

优点

  • (1)在工厂方法模式中,用户无需关心实现细节,只需要关系所对应的工厂即可
  • (2)多态性是工厂方法模式的关键。它能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以被称为多态工厂模式,就是因为所有的具体工厂类都具有同一抽象父类。
  • (3)加入新产品类时,无需修改抽象工厂和抽象工厂接口,而只要添加一个具体工厂和具体产品即可,这样,系统的可扩展性也就变得非常好,完全符合开闭原则。

缺点

  • (1)添加新产品类时,需要添加具体的工厂类,增加系统复杂度,带来额外的开销
  • (2)由于考虑到系统的可扩展性,需要引人抽象层,增加理解难度

适用环境

  • (1)客户端不知道它所需要的对象的类
  • (2)抽象工厂类通过其子类来指定创建哪个对象。

抽象工厂模式

与工厂方法模式不同,每个工厂类不只是生产一种,而是生产多个

定义

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

结构

抽象工厂方法模式结构.png

  • (1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
  • (2)ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
  • (3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
  • (4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

实现

//产品A属性
class ProductA
{
    private int _id;
    public int ID
    {
        get { return _id; }
        set { _id = value; }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

//产品B属性
class ProductB
{
    private int _id;
    public int ID
    {
        get { return _id; }
        set { _id = value; }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

//抽象工厂
interface IAbstractFactory
{
    IAbstractProudctA CreateProductA();
    IAbstractProudctB CreateProductB();
}

//具体工厂A
class ConcreteFactoryA : IAbstractFactory
{
    public IAbstractProudctA CreateProductA()
    {
        return new ConcreteProductA();
    }

    public IAbstractProudctB CreateProductB()
    {
        return new ConcreteProductB();
    }
}

//具体工厂B
class ConcreteFactoryB : IAbstractFactory
{
    public IAbstractProudctA CreateProductA()
    {
        return new ConcreteProductA();
    }

    public IAbstractProudctB CreateProductB()
    {
        return new ConcreteProductB();
    }
}

//抽象产品A
interface IAbstractProudctA
{
    void ConcreteProductA1(ProductA user);
    ProductA ConcreteProductA2(int id);
}

//抽象产品B
interface IAbstractProudctB
{
    void ConcreteProductB1(ProductB user);
    ProductB ConcreteProductB2(int id);
}


//具体产品A
class ConcreteProductA : IAbstractProudctA
{
    public ProductA ConcreteProductA2(int id)
    {
        //产品具体实现
        Console.WriteLine("在ConcreteProductA中获取ProductA表记录");
        return null;
    }

    public void ConcreteProductA1(ProductA user)
    {
        //产品具体实现
        Console.WriteLine("在ConcreteProductA中给ProductA表增加一条记录");
    }
}

class ConcreteProductB : IAbstractProudctB
{
    public ProductB ConcreteProductB2(int id)
    {
        //产品具体实现
        return null;
    }

    public void ConcreteProductB1(ProductB user)
    {
        //产品具体实现
    }
}

class Program
{
    static void Main(string[] args)
    {
        ProductA abstractProductA = new ProductA();
        ProductB abstractProductB = new ProductB();
        IAbstractFactory abstractFactory = new ConcreteFactoryA();    //只需确定实例化哪个

        IAbstractProudctA concreteProductA = abstractFactory.CreateProductA();
        concreteProductA.ConcreteProductA1(abstractProductA);
        concreteProductA.ConcreteProductA2(2);

        IAbstractProudctB concreteProductB = abstractFactory.CreateProductB();
        concreteProductB.ConcreteProductB1(abstractProductB);
        concreteProductB.ConcreteProductB2(2);
    }
}

优点

  • (1)抽象工厂模式隔离了具体类的生成,使得客户端并不需要知道什么被创建。
  • (2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
  • (3)抽象工厂模式增加新的产品族很方便,无须修改已有系统,符合开闭原则。

缺点

增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则。

适用环境

  • (1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
  • (2)系统中有多于一个的产品族,但每次只使用其中某一产品族,可以通过配置文件等方式使用户能够动态地改变产品族,也可以很方便地增加新的产品族。
  • (3)属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
  • (4)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。
分享到:
设计模式-建造者模式
Lua反射
  • 文章目录
  • 站点概览
欢

网红 欢

你能抓到我么?

Email RSS
看爆 Top5
  • mac系统版本与Xcode版本有冲突 4,080次看爆
  • JAVA_HOME环境配置问题 3,730次看爆
  • AssetBundle使用 3,499次看爆
  • VSCode配置C++开发环境 3,257次看爆
  • Lua反射 3,133次看爆

Copyright © 2025 欢 粤ICP备2020105803号-1

由 Halo 强力驱动 · Theme by Sagiri · 站点地图