设计模式之简单工厂模式、工厂模式、抽象工厂模式 C#实现

创建型模式

说明
记录设计模式之禅的学习之路,并用C#实现之。

工厂模式

定义

Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.
(定义一个用于创建对象的 接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
在这里插入图片描述
在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定 义;
Creator为抽象创建类,也就是抽象工厂,
具体如何创建产品类是由具体的实现工厂 ConcreteCreator完成的。

    public interface Human
    {     //每个人种的皮肤都有相应的颜色     
        public void getColor();
        //人类会说话     
        public void talk();
    }
  public class BlackHuman : Human
    {
        public void getColor()
        {
            Console.WriteLine("黑色人种的皮肤颜色是黑色的!");
        }
        public void talk()
        {
            Console.WriteLine("黑人会说话,一般人听不懂。");
        }
    }
   public class YellowHuman : Human
    {
        public void getColor()
        {
            Console.WriteLine("黄色人种的皮肤颜色是黄色的!");
        }
        public void talk()
        {
            Console.WriteLine("黄种人会说话,说汉语。");
        }
    }
  public class HumanFactory//: AbstractHumanFactory<T>
    {
     public Human createHuman(string c)
        {
            //定义一个生产的人种
            Human human = null;
            try
            {                      //产生一个人种
                switch (c)
                {
                    case "black":
                        human = new BlackHuman();
                        break;
                    case "yellow":
                        human = new YellowHuman();
                        break;
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("人种生成错误!");
            }
            return human;
        }
    }
    public class NvWa
    {
        public void dosth()
        {
            HumanFactory YinYangLu = new HumanFactory();
            Human whiteHuman = YinYangLu.createHuman("black");
            whiteHuman.getColor();
            whiteHuman.talk();
        }
    }

工厂方法模式的应用

优点

良好的封装性,代码结构清晰。
一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,
只要知道这个产品的类名(或约束字符串)就可以了,
不用知道创 建对象的艰辛过程,降低模块间的耦合。
工厂方法模式的扩展性非常优秀
在增加产品类的情况下,只要适当地修改具体 的工厂类或扩展一个工厂类,
就可以完成“拥抱变化”。
例如在我们的例子中,需要增加一个 棕色人种,则只需要增加一个BrownHuman类,工厂类不用任何修改就可完成系统扩展。(本例中需要进行修改工厂类)
屏蔽产品类
这一特点非常重要,产品类的实现如何变化,调用者都不需要关 心,
它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
因为产品类的实例化工作是由工厂类负责的,一个产品对象具体由哪一个产品生成是由工厂类 决定的。
在数据库开发中,大家应该能够深刻体会到工厂方法模式的好处:
如果使用JDBC 连接数据库,数据库从MySQL切换到Oracle,
需要改动的地方就是切换一下驱动名称(前提 条件是SQL语句是标准语句),
其他的都不需要修改,这是工厂方法模式灵活性的一个直接 案例。

工厂方法模式是典型的解耦框架
高层模块值需要知道产品的抽象类,其他的实 现类都不用关心,符合迪米特法则,我不需要的就不要去交流;
也符合依赖倒置原则,只依赖产品类的抽象;
当然也符合里氏替换原则,使用产品子类替换产品父类,没问题!

使用场景

工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以 使用,
但是需要慎重地考虑是否要增加一个工厂类进行管理,增加代码的复杂度
需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
例如需要设计一个连接邮件服务器的框架,有三种网络协议可供选择:
工厂方法模式可以用在异构项目中,例如通过WebService与一个非Java的项目交 互
可以使用在测试驱动开发的框架下。

工厂方法模式的扩展
1. 缩小为简单工厂模式

一个模块仅需要一个工厂类,没有必要把它产生出来,使用静 态的方法就可以了,

2. 升级为多个工厂类

当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所
有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰。例如,一个产品类有5 个具体实现,每个实现类的初始化(不仅仅是new,初始化包括new一个对象,并对对象设 置一定的初始值)方法都不相同,如果写在一个工厂方法中,势必会导致该方法巨大无比, 那该怎么办?
考虑到需要结构清晰,我们就为每个产品定义一个创造者,然后由调用者自己去选择与 哪个工厂方法关联
每一个产品类都对应了一个创建类,好处就是创建 类的职责清晰,而且结构简单,但是给可扩展性和可维护性带来了一定的影响。为什么这么 说呢?如果要扩展一个产品类,就需要建立一个相应的工厂类,这样就增加了扩展的难度。 因为工厂类和产品类的数量相同,维护时需要考虑两个对象之间的关系。 当然,在复杂的应用中一般采用多工厂的方法,然后再增加一个协调类,避免调用者与 各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口。

3. 替代单例模式

通过反射的方式建立一个单例对象

4. 延迟初始化

何为延迟初始化(Lazy initialization)?一个对象被消费完毕后,并不立刻释放,工厂类 保持其初始状态,等待再次被使用。

ProductFactory负责产品类对象的创建工作,并且通过prMap变量产生一个缓存,对需要 再次被重用的对象保留
代码还比较简单,通过定义一个Map容器,容纳所有产生的对象,如果在Map容器中已 经有的对象,则直接取出返回;如果没有,则根据需要的类型产生一个对象并放入到Map容 器中,以方便下次调用。 延迟加载框架是可以扩展的,例如限制某一个产品类的最大实例化数量,可以通过判断 Map中已有的对象数量来实现,这样的处理是非常有意义的,例如JDBC连接数据库,都会 要求设置一个MaxConnections最大连接数量,该数量就是内存中最大实例化的数量。 延迟加载还可以用在对象初始化比较复杂的情况下,例如硬件访问,涉及多方面的交 互,则可以通过延迟加载降低对象的产生和销毁带来的复杂性。

抽象工厂模式

抽象,是指其父类是抽象类?

定义

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们 的具体类。)

在有多个业务品种、业务分类时,通过抽象 工厂模式产生需要的对象是一种非常好的解决方式。

抽象工厂模式的应用

抽象工厂模式的优点

● 封装性,每个产品的实现类不是高层模块要关心的,
它要关心的是什么?是接口,是 抽象,
它不关心对象是如何创建出来,这由谁负责呢?工厂类,只要知道工厂类是谁,我就 能创建出一个需要的对象,省时省力,优秀设计就应该如此。
● 产品族内的约束为非公开状态。
例如生产男女比例的问题上,猜想女娲娘娘肯定有自 己的打算,不能让女盛男衰,否则女性的优点不就体现不出来了吗?
那在抽象工厂模式,就 应该有这样的一个约束:
每生产1个女性,就同时生产出1.2个男性,这样的生产过程对调用 工厂类的高层模块来说是透明的,
它不需要知道这个约束,我就是要一个黄色女性产品就可以了,具体的产品族内的约束是在工厂内实现的。

抽象工厂模式的缺点

抽象工厂模式的最大缺点就是产品族扩展非常困难
为什么这么说呢?我们以通用代码 为例,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,看看我们的程序 有多大改动吧!
抽象类AbstractCreator要增加一个方法createProductC(),然后两个实现类都要 修改,
想想看,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。
改变 契约,所有与契约有关系的代码都要修改,那么这段代码叫什么?叫“有毒代码”,——只要 与这段代码有关系,就可能产生侵害的危险!

抽象工厂模式的注意事项

在抽象工厂模式的缺点中,我们提到抽象工厂模式的产品族扩展比较困难,
但是一定要 清楚,是产品族扩展困难,而不是产品等级。
在该模式下,产品等级是非常容易扩展的,增 加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。
也就是说横向 扩展容易,纵向扩展困难。
以人类为例子,产品等级中只有男、女两个性别,现实世界还有 一种性别:双性人,既是男人也是女人(俗语就是阴阳人),
那我们要扩展这个产品等级也 是非常容易的,增加三个产品类,分别对应不同的肤色,
然后再创建一个工厂类,专门负责 不同肤色人的双性人的创建任务,
完全通过扩展来实现需求的变更,
从这一点上看,抽象工 厂模式是符合开闭原则的。

最佳实践

一个模式在什么情况下才能够使用,是很多读者比较困惑的地方。抽象工厂模式是一个 简单的模式,使用的场景非常多,大家在软件产品开发过程中,涉及不同操作系统的时候, 都可以考虑使用抽象工厂模式,例如一个应用,需要在三个不同平台(Windows、Linux、 Android(Google发布的智能终端操作系统))上运行,你会怎么设计?分别设计三套不同 的应用?非也,通过抽象工厂模式屏蔽掉操作系统对应用的影响。三个不同操作系统上的软 件功能、应用逻辑、UI都应该是非常类似的,唯一不同的是调用不同的工厂方法,由不同的 产品类去处理与操作系统交互的信息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#实现抽象工厂模式,需要定义一个抽象工厂类,其中包含多个抽象方法,用于创建不同类别的产品对象然后,创建具体的工厂类,继承抽象工厂类,并实现抽象方法,具体工厂类负责创建具体的产品对象。最后,定义产品类,用于表示具体的产品对象。 以下是一个简单的抽象工厂模式示例: ```csharp // 抽象产品类 abstract class Product { public abstract void Show(); } // 具体产品类A class ConcreteProductA : Product { public override void Show() { Console.WriteLine("This is product A."); } } // 具体产品类B class ConcreteProductB : Product { public override void Show() { Console.WriteLine("This is product B."); } } // 抽象工厂类 abstract class Factory { public abstract Product CreateProductA(); public abstract Product CreateProductB(); } // 具体工厂类X class ConcreteFactoryX : Factory { public override Product CreateProductA() { return new ConcreteProductA(); } public override Product CreateProductB() { return new ConcreteProductB(); } } // 具体工厂类Y class ConcreteFactoryY : Factory { public override Product CreateProductA() { return new ConcreteProductB(); } public override Product CreateProductB() { return new ConcreteProductA(); } } ``` 在上面的示例中,抽象工厂类 `Factory` 定义了两个抽象方法 `CreateProductA()` 和 `CreateProductB()`,用于创建具体的产品对象。具体工厂类 `ConcreteFactoryX` 和 `ConcreteFactoryY` 继承抽象工厂类 `Factory` 并实现了抽象方法,用于创建具体产品对象。 当需要创建产品对象时,可以先实例化具体工厂类,然后调用其方法创建所需的具体产品对象: ```csharp Factory factory = new ConcreteFactoryX(); Product productA = factory.CreateProductA(); Product productB = factory.CreateProductB(); productA.Show(); // 输出 "This is product A." productB.Show(); // 输出 "This is product B." ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值