【设计模式】简单工厂模式(C#)

【设计模式】简单工厂模式(C#)

1、概述

工厂模式总结三个要点:

  • 不想直接new这个类的对象,防止这个类改变的时候在new的地方到处去改,麻烦且容易遗漏;
  • 这个类的对象构建过程非常复杂,不想在代码的各个地方将这么复杂的构建过程反复书写;
  • 这个类的对象在构建过程中依赖了很多其他的类,而你无法在调用的地方提供。

2、结构

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

3、背景

需求:设计一个披萨点餐系统。

设计一个披萨类(Pizza),并定义其两个子类(奶酪披萨【CheessPizza】和希腊披萨【GreekPizza】);再设计一个披萨店类(PizzaStore),披萨店具有点披萨的功能。

首先,我们先实现上述的需求。

//1.抽象产品
public abstract class Pizza
    {
        //名字
        public string Name;

        //准备原材料
        public abstract void Prepare();

        public void Bake()
        {
            Console.WriteLine($"{this.Name} bake");
        }

        public void Cut()
        {
            Console.WriteLine($"{this.Name} cut");
        }

        public void Box()
        {
            Console.WriteLine($"{this.Name} box");
        }

    }

//2.具体产品
public class CheessPizza : Pizza
    {
        public override void Prepare()
        {
            Console.WriteLine("CheessPizza 准备原材料");
        }
    }

//2.具体产品
public class GreekPizza : Pizza
    {
        public override void Prepare()
        {
            Console.WriteLine("GreekPizza 准备原材料");
        }
    }

//3.产品商店
    public class PizzaStore
    {
        public static Pizza OrderPizza(string type)
        {
            Pizza pizza = null;
            switch (type)
            {
                case "greek":
                    pizza = new GreekPizza();
                    pizza.Name = "希腊披萨";
                    break;
                case "cheess":
                    pizza = new CheessPizza();
                    pizza.Name = "奶酪披萨";
                    break;
                default:
                    break;
            }
            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();
            return pizza;
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            PizzaStore.OrderPizza("greek");
            PizzaStore.OrderPizza("cheess");
        }
    }

此时,如果我们要新增一个披萨商店,那个就需要增加一个【PizzaStore1】类;当我们要增加一款新的披萨产品(水果披萨【FruitPizza】)时, 我们要去修改每一个披萨商店的OrderPizza方法,也就是产品类和商店类耦合,违反了开闭原则(对于扩展是开放的,但是对于修改是封闭的);

那么有没有办法将产品类和商店类解耦呢?答案是有的,就是引入工厂模式。

4、简单工厂模式

我们首先引入简单工厂,

//具体工厂
public class PizzaSimpleFactory
    {
        public static Pizza CreatPizza(string type)
        {
            Pizza pizza = null;
            switch (type)
            {
                case "greek":
                    pizza = new GreekPizza();
                    pizza.Name = "希腊披萨";
                    break;
                case "cheess":
                    pizza = new CheessPizza();
                    pizza.Name = "奶酪披萨";
                    break;
                default:
                    break;
            }
            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();
            return pizza;
        }
    }
//产品商店
public class PizzaStore
    {
        public static Pizza OrderPizza(string type)
        {
            Pizza pizza = PizzaSimpleFactory.CreatPizza(type);
            return pizza;
        }
    }

可以看出,简单工厂模式的出现,使得我们通过传入不同的参数类型就可以创建不同类型的对象实例,将对象的构建过程完全交给了简单工厂方法类SimpleFactory。我们要增加一款新的披萨产品(水果披萨【FruitPizza】)时,只需要修改【PizzaSimpleFactory】。

一旦有了PizzaSimpleFactory,PizzaStore类中的OrderPizza()就变成此对象的客户,后期如果需要Pizza对象直接从工厂中获取即可。这样也就解除了和Pizza实现类的耦合,同时又产生了新的耦合,PizzaStore对象和SimplePizzaFactory工厂对象的耦合,工厂对象和商品对象的耦合。

但是,后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。

5、简单工厂模式的缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,同样违背了“开闭原则”。

为了克服简单工厂模式的缺点,工厂方法模式就被提了出来,我们下篇文章再介绍。

你可能感兴趣的:(设计模式,设计模式,简单工厂模式,c#)