我们知道简单工厂模型其实有很多缺点,比如我们要继续扩展产品的时候必须要自己写一个实现类去继承抽象方法,还要修改工厂类

所以,简单工厂是明显的违背了开-闭原则的。

先来给出工厂方法的结构图吧

 

c# 工厂方法模型
    


            
c# 工厂方法模型

上面的类图稍微简单了点,但是还是可以反映出一些内容的,

和简单工厂相比的话,在工厂方法中,创建对象将不会在集中在一个类中了,

而是通过一个 FactoryMethod 方法在各个子类中实现对象的实例化,

这句话怎么理解呢?

也就是,在上面的类图中,

创建 ConcreteProduct 类的实例这个功能被封装在了 ConcreteProductFactory 中,

而不是在 ProductFactory 中了,

下面再看一副稍微复杂点的类图或许能够帮助更好的理解

c# 工厂方法模型
    


            
c# 工厂方法模型

上面的类图稍微简单了点,但是还是可以反映出一些内容的,

和简单工厂相比的话,在工厂方法中,创建对象将不会在集中在一个类中了,

而是通过一个 FactoryMethod 方法在各个子类中实现对象的实例化,

这句话怎么理解呢?

也就是,在上面的类图中,

创建 ConcreteProduct 类的实例这个功能被封装在了 ConcreteProductFactory 中,

而不是在 ProductFactory 中了,

下面再看一副稍微复杂点的类图或许能够帮助更好的理解

c# 工厂方法模型
    


            
c# 工厂方法模型

从上面的类图中可以看到,拥有一个水果抽象类 Fruit

然后是四个水果具体类,还有一个水果工厂抽象类 FruitFactory ,

然后是四个具体工厂类,分别用来创建四个水果具体类的实例。

下面就来看代码啦

先是 Fruit 抽象类

namespace FactoryMethod 

    public abstract class Fruit 
    { 
        public abstract void Display(); 
    } 
}

然后是四个具体的水果类

using System;

namespace FactoryMethod 

    class Apple:Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:苹果 ,主要特性为养颜护肤"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Banana:Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:香蕉 ,主要特性为滋肝润胃"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Orange : Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:橘子 ,主要特性为滋肝润胃"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Pear : Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:梨子 ,主要特性为滋肝润胃"); 
        } 
    } 
}

再来看抽象工厂类 FruitFactory

namespace FactoryMethod 

    public abstract class FruitFactory 
    { 
        public abstract Fruit GetFruit(); 
    } 
}

然后就是四个具体工厂类

namespace FactoryMethod 

    public class AppleFactory:FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Apple(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class BananaFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Banana(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class OrangeFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Orange(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class PearFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Pear(); 
        } 
    } 
}

所有的类的结构的代码就在上面了,下面将要看的就是客户端代码和效果了

using System; 
using FactoryMethod;

namespace FactoryMethodTest 

    class Program 
    { 
        static void Main(string[] args) 
        { 
            FruitFactory factory; 
            Fruit fruit;

            //首先要实例化一个苹果工厂 
            factory = new AppleFactory(); 
            //然后通过工厂来获得苹果类对象 
            fruit = factory.GetFruit(); 
            //访问苹果类对象 
            fruit.Display();

            //首先要实例化一个梨子工厂 
            factory = new PearFactory(); 
           //然后通过工厂来获得梨子类对象 
            fruit = factory.GetFruit(); 
           //访问梨子类对象 
            fruit.Display();

            Console.ReadLine(); 
        } 
    } 
}

 

下面将通过比较简单工厂和工厂方法这两种设计模式来体现出各自的优劣之处:

 

简单工厂把全部的事情,在一个地方(类)全部处理完,而工厂方法却不同,

 

其是通过创建一个框架(FruitFactory),

 

然后让子类(AppleFactory 等)决定要如何实现,简单工厂呢,其将对象的创建封装起来了,

 

但是其违背开-闭原则,弹性太弱,正如前面介绍简单工厂时,提到的加入一种水果葡萄时会造成修改类,

 

而工厂方法则恰恰解决了简单工厂的这一毛病,其通过将实例化延迟到子类成功解决了简单工厂的这一问题,

 

其实呢,可以这样去理解,简单工厂在其主要的工厂方法中,存在了逻辑判断语言,

 

这是因为,工厂方法必须根据外界给出的条件来创建符合要求的实例,

 

而工厂方法却不存在这一点,也就是不需要指到外界的情况,

 

这是为何呢?其实这是因为,工厂方法将这些本来应该存在的判断逻辑移到了客户端代码中,

 

(通过客户的需求来选择生成那一种水果实例,比如我的演示中生成的就是苹果和梨子这两种实例)

 

这样的话,可以解决掉简单工厂违背开-闭原则这一毛病,

 

比如,要在上面的 Demo 中再添加一种水果 Grape 的话,

 

使用工厂方法的话,您只需要添加一个 Grape 类,让其继承自 Fruit ,

 

然后再为其添加一个 GrapeFactory 类,让这个类继承自 FruitFactory 类就 OK 了,

 

其余的代码便是在客户端来完成了。

我们知道简单工厂模型其实有很多缺点,比如我们要继续扩展产品的时候必须要自己写一个实现类去继承抽象方法,还要修改工厂类

所以,简单工厂是明显的违背了开-闭原则的。

先来给出工厂方法的结构图吧

 

c# 工厂方法模型
    


            
c# 工厂方法模型

上面的类图稍微简单了点,但是还是可以反映出一些内容的,

和简单工厂相比的话,在工厂方法中,创建对象将不会在集中在一个类中了,

而是通过一个 FactoryMethod 方法在各个子类中实现对象的实例化,

这句话怎么理解呢?

也就是,在上面的类图中,

创建 ConcreteProduct 类的实例这个功能被封装在了 ConcreteProductFactory 中,

而不是在 ProductFactory 中了,

下面再看一副稍微复杂点的类图或许能够帮助更好的理解

c# 工厂方法模型
    


            
c# 工厂方法模型

上面的类图稍微简单了点,但是还是可以反映出一些内容的,

和简单工厂相比的话,在工厂方法中,创建对象将不会在集中在一个类中了,

而是通过一个 FactoryMethod 方法在各个子类中实现对象的实例化,

这句话怎么理解呢?

也就是,在上面的类图中,

创建 ConcreteProduct 类的实例这个功能被封装在了 ConcreteProductFactory 中,

而不是在 ProductFactory 中了,

下面再看一副稍微复杂点的类图或许能够帮助更好的理解

c# 工厂方法模型
    


            
c# 工厂方法模型

从上面的类图中可以看到,拥有一个水果抽象类 Fruit

然后是四个水果具体类,还有一个水果工厂抽象类 FruitFactory ,

然后是四个具体工厂类,分别用来创建四个水果具体类的实例。

下面就来看代码啦

先是 Fruit 抽象类

namespace FactoryMethod 

    public abstract class Fruit 
    { 
        public abstract void Display(); 
    } 
}

然后是四个具体的水果类

using System;

namespace FactoryMethod 

    class Apple:Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:苹果 ,主要特性为养颜护肤"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Banana:Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:香蕉 ,主要特性为滋肝润胃"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Orange : Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:橘子 ,主要特性为滋肝润胃"); 
        } 
    } 
}

 

using System;

namespace FactoryMethod 

    class Pear : Fruit 
    { 
        public override void Display() 
        { 
            Console.WriteLine("我的名字是:梨子 ,主要特性为滋肝润胃"); 
        } 
    } 
}

再来看抽象工厂类 FruitFactory

namespace FactoryMethod 

    public abstract class FruitFactory 
    { 
        public abstract Fruit GetFruit(); 
    } 
}

然后就是四个具体工厂类

namespace FactoryMethod 

    public class AppleFactory:FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Apple(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class BananaFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Banana(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class OrangeFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Orange(); 
        } 
    } 
}

 

namespace FactoryMethod 

    public class PearFactory : FruitFactory 
    { 
        public override Fruit GetFruit() 
        { 
            return new Pear(); 
        } 
    } 
}

所有的类的结构的代码就在上面了,下面将要看的就是客户端代码和效果了

using System; 
using FactoryMethod;

namespace FactoryMethodTest 

    class Program 
    { 
        static void Main(string[] args) 
        { 
            FruitFactory factory; 
            Fruit fruit;

            //首先要实例化一个苹果工厂 
            factory = new AppleFactory(); 
            //然后通过工厂来获得苹果类对象 
            fruit = factory.GetFruit(); 
            //访问苹果类对象 
            fruit.Display();

            //首先要实例化一个梨子工厂 
            factory = new PearFactory(); 
           //然后通过工厂来获得梨子类对象 
            fruit = factory.GetFruit(); 
           //访问梨子类对象 
            fruit.Display();

            Console.ReadLine(); 
        } 
    } 
}

 

下面将通过比较简单工厂和工厂方法这两种设计模式来体现出各自的优劣之处:

 

简单工厂把全部的事情,在一个地方(类)全部处理完,而工厂方法却不同,

 

其是通过创建一个框架(FruitFactory),

 

然后让子类(AppleFactory 等)决定要如何实现,简单工厂呢,其将对象的创建封装起来了,

 

但是其违背开-闭原则,弹性太弱,正如前面介绍简单工厂时,提到的加入一种水果葡萄时会造成修改类,

 

而工厂方法则恰恰解决了简单工厂的这一毛病,其通过将实例化延迟到子类成功解决了简单工厂的这一问题,

 

其实呢,可以这样去理解,简单工厂在其主要的工厂方法中,存在了逻辑判断语言,

 

这是因为,工厂方法必须根据外界给出的条件来创建符合要求的实例,

 

而工厂方法却不存在这一点,也就是不需要指到外界的情况,

 

这是为何呢?其实这是因为,工厂方法将这些本来应该存在的判断逻辑移到了客户端代码中,

 

(通过客户的需求来选择生成那一种水果实例,比如我的演示中生成的就是苹果和梨子这两种实例)

 

这样的话,可以解决掉简单工厂违背开-闭原则这一毛病,

 

比如,要在上面的 Demo 中再添加一种水果 Grape 的话,

 

使用工厂方法的话,您只需要添加一个 Grape 类,让其继承自 Fruit ,

 

然后再为其添加一个 GrapeFactory 类,让这个类继承自 FruitFactory 类就 OK 了,

 

其余的代码便是在客户端来完成了。

相关文章: