New

这是一个典型的情况, 我们需要在运行时来实例化一些具体的类. 在需要修改或者扩展的时候我们就需要改这段代码. 一个程序中可能会多次出现类似的代码, 这使得维护和更新非常困难而且容易出错.

通过面向接口的编程, 我们可以把自己从各种变化中隔离出来, 因为如果代码是面向接口的话, 那么通过多态机制, 任何实现了该接口的新类都可以直接被使用.

所以别忘了设计原则: 对修改关闭.

需求

假设你是个披萨店老板, 有以下代码:

这是订购披萨的过程.

而你可能需要多种披萨:

这里就是根据参数来创建不同类型的披萨实例. 然后再进行下一步操作.

但是这样的事情可能会发生: 添加新类型披萨, 淘汰某些类型的披萨.

对代码修修改改. 所以这不是对修改关闭. 上面那部分代码需要修修改改, 下面那部分代码是固定不变的. 那最好的办法就是封装它.

封装对象的创建

需要把变化的部分封装起来, 也就是把创建披萨那部分代码移动到另外一个对象里, 而这个对象将专注于创建披萨.

针对这种对象, 它有一个名字, 叫工厂(Factory). 工厂会处理对象创建的细节.

建立一个简单的披萨工厂

这个类只有一个任务: 为客户创建披萨.

为什么不适用静态(static)方法?

可以使用static方法, 这样的话你就不需要创建一个对象然后再调用方法了. 但是这么做也有一个缺点, 那就是不可以对它继承了, 也无法改变create方法的行为了.

使用SimpleFactory之后:

简单工厂 Simple Factory

简单工厂实际上并不是设计模式, 可以更多的认为是一种编程范式. 但是使用的却是非常广泛.

理清一下目前的情况:

C#实现:

namespace C04FactoryPattern.Bases
{
    public interface IPizza
    {
        string Type {  get; }
        void Prepare();
        void Bake();
        void Cut();
        void Box();
    }
}

namespace C04FactoryPattern.Bases
{
    public interface IPizzaStore
    {
        Pizza OrderPizza(string type);
    }
}

namespace C04FactoryPattern.Bases
{
    public abstract class Pizza: IPizza
    {
        public abstract string Type { get;}

        public void Prepare()
        {
            Console.WriteLine($"{Type} is Preparing...");
        }

        public void Bake()
        {
            Console.WriteLine($"{Type} is Baking...");
        }

        public void Cut()
        {
            Console.WriteLine($"{Type} is Cutting...");
        }

        public void Box()
        {
            Console.WriteLine($"{Type} is Boxing...");
        }
    }
}
namespace C04FactoryPattern.Models
{
    public class CheesePizza : Pizza
    {
        public override string Type => nameof(CheesePizza);
    }

    public class ClamPizza : Pizza
    {
        public override string Type => nameof(ClamPizza);
    }

    public class PepperoniPizza : Pizza
    {
        public override string Type => nameof(PepperoniPizza);
    }

    public class VeggiePizza : Pizza
    {
        public override string Type => nameof(VeggiePizza);
    }
}
namespace C04FactoryPattern.SimpleFactory
{
    public class SimplePizzaFactory
    {
        public Pizza CreatePizza(string type)
        {
            Pizza pizza = null;
            switch (type)
            {
                case nameof(CheesePizza):
                    pizza = new CheesePizza();
                    break;
                case nameof(ClamPizza):
                    pizza = new ClamPizza();
                    break;
                case nameof(PepperoniPizza):
                    pizza = new PepperoniPizza();
                    break;
                case nameof(VeggiePizza):
                    pizza = new VeggiePizza();
                    break;
            }
            return pizza;
        }
    }
}
namespace C04FactoryPattern.SimpleFactory
{
    public class PizzaStore: IPizzaStore
    {
        private readonly SimplePizzaFactory _factory;

        public PizzaStore(SimplePizzaFactory factory)
        {
            _factory = factory;
        }

        public Pizza OrderPizza(string type)
        {
            var pizza = _factory.CreatePizza(type);
            if (pizza != null)
            {
                pizza.Prepare();
                pizza.Bake();
                pizza.Cut();
                pizza.Box();
                Console.WriteLine($"{type} Done!!!");
            }
            else
            {
                Console.WriteLine("We don't have this kind of pizza!!");
            }
            return pizza;
        }
    }
}

测试:

namespace C04FactoryPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Simple Factory:");
            PizzaStore pizzaStore = new PizzaStore(new SimplePizzaFactory());
            pizzaStore.OrderPizza(nameof(CheesePizza));
            pizzaStore.OrderPizza(nameof(PepperoniPizza));
            Console.ReadLine();
        }
    }
}

设计模式学习(四): 1.简单工厂 (附C#实现)的更多相关文章

  1. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  2. C#设计模式学习笔记:简单工厂模式(工厂方法模式前奏篇)

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7551373.html,记录一下学习过程以备后续查用. 一.引言 简单工厂模式并不属于GoF23里面的设计模式 ...

  3. C#设计模式学习笔记:(2)工厂方法模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7567880.html,记录一下学习过程以备后续查用. 一.引言 接上一篇C#设计模式学习笔记:简单工厂模式( ...

  4. 设计模式(二)简单工厂模式(Simple Factory Pattern)

    一.引言 这个系列也是自己对设计模式的一些学习笔记,希望对一些初学设计模式的人有所帮助的,在上一个专题中介绍了单例模式,在这个专题中继续为大家介绍一个比较容易理解的模式——简单工厂模式. 二.简单工厂 ...

  5. 设计模式的征途—2.简单工厂(Simple Factory)模式

    工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的“小弟”,我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应 ...

  6. Java设计模式(一) 简单工厂模式不简单

    摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...

  7. <一>读<<大话设计模式>>之简单工厂模式

    工厂模式尽管简单.可是写下这篇文章却不简单. 第一:本人经过内心的挣扎后才决定開始写博文的.为什么呢,由于好长时间没有写了,对自己的文学功底也是好不自信.可是技术这东西你不写出来你真不知道自己掌握多少 ...

  8. PHP设计模式(一)简单工厂模式 (Simple Factory For PHP)

    最近天气变化无常,身为程序猿的寡人!~终究难耐天气的挑战,病倒了,果然,程序猿还需多保养自己的身体,有句话这么说:一生只有两件事能报复你:不够努力的辜负和过度消耗身体的后患.话不多说,开始吧. 一.什 ...

  9. 设计模式(四)抽象工厂模式(Abstract Factory Pattern)

    一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码,而工厂方法模式每个具体工厂类只完成单个实例的创建 ...

随机推荐

  1. Spring 面试

    1.什么是Spring框架?Spring框架有哪些主要模块? spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题, ...

  2. Android 高仿QQ5.2双向側滑菜单DrawerLayout实现源代码

    Android 高仿QQ5.2双向側滑菜单DrawerLayout实现源代码 左右側滑效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a ...

  3. javascript跳跃式前进(3) - 跳入JSON

    前言 JSON崛起不是意外,是顺应时代;相当简洁小巧的书写模式及阅读方式; 基础 看这篇文章: JSON知识点汇总_W3SCHOOL 初步进阶 早期的解析仅仅实用eval() ,可是这货太easy给注 ...

  4. 使用storyboard设置button边框属性(颜色,宽度,圆角)

    通常使用Category时.仅仅能加入方法,不可加入属性.可是在使用Storyboard时我们可能会使用到keyPath,这里设置的key都须要是所设置视图的属性值.而且类型有所限制. 比如:我如今有 ...

  5. Maven实战(九)——打包的技巧

    "打包"这个词听起来比較土.比較正式的说法应该是"构建项目软件包".详细说就是将项目中的各种文件,比方源代码.编译生成的字节码.配置文件.文档,依照规范的格式生 ...

  6. 用js把图片做的富有动态感,并对以后需要用着的属性进行封装

    首先我们先要导入几张图片(我已导入完毕): : 好,我们先写一个 <div ></div>, 定义一个 class="contair", 在这<div ...

  7. Android系统拍照之后回显并且获取文件路径

    /*调用拍照返回*/ case PHOTO_REQUEST_GALLERY: if (data != null) { Uri uri = data.getData(); String photopat ...

  8. C#中的GET和SET访问器

    我们在学习C#语法的属性时,都要首先和GET,SET访问器打交道,从英文的字面意思上理解,GET应该就是获得什么什么,而SET应该是设置什么什么,那我们看一下,官方是怎么定义这对访问器的:get是读取 ...

  9. H5之前端操作文件

    js是否能够操作文件? js在HTML5以前浏览器端是无法操作文件的,但HTML5中给a标签增加了一个download属性,只要有这个属性,点击这个链接时浏览器就不在打开链接指向的文件,而是改为下载( ...

  10. iOS PickerView选择视图

    原文demo: @interface ViewController ()<UIPickerViewDelegate,UIPickerViewDataSource> { UIPickerVi ...