C#设计模式<二>工厂模式

接上节:

单例设计模式的关键点

一.私有构造函数

二.声明静态单例对象

三.构造单例对象之前要加锁(lock一个静态的object对象,某些语言可以声明同步执行,其实是一个目的)

四.需要两次检测单例实例是否已经被构造,分别在锁之前和锁之后

工厂模式

经典模式之一,其核心功能是根据“需求”生产“产品”,设计模式的核心是解耦吗?工厂模式就是为了解耦“需求”和“产品”,但是别忘了,工厂模式工厂模式,还有一个重要元素,就是“工厂”,所以工厂模式的核心思想,就是解耦“需求”“工厂”和“产品”。对于一般初学者Get这个技能比学会单例模式要有逼格。无论是炫技也罢,还是真正利用设计模式解耦,都是一种成长不是吗?总共有三种类型我们分别讨论。主要以实际题目为引导。

题目

/*
很多人都喜欢带手表,手表的种类很多,主要分为石英表,机械表,光能表。
所有的手表都有自己的名字;
所有的手表都有年月日时分秒(6个属性),并且可以显示时间;
所有的手表都可以连续打出五次自己的广告语;
机械表可以自动上弦;
石英表中的天梭(TISSOT)和机械表中的欧米茄(OMEGA)有秒表计时功能(不需要实现计时的具体逻辑);
光能表中的卡西欧(CASIO)可以计算X天之后是哪一天(需要自己实现逻辑,不能使用C#自带的DateTime类,注意闰年);


现在大连有一家表店有如下这些手表:
机械表:欧米茄(OMEGA),万国(IWC )
光能表:卡西欧(CASIO),西铁城(CITIZEN)
石英表:天梭(TISSOT),雷达(RADO)


写一个方法,让这些手表按顺序展示下自己的功能。


评分细则: 
程序是用面向对象的思想设计的。 (20分) 
合理的设计类,以及父子类之间的继承关系。 (20分) 
合理设计接口,合理使用属性。(15分)
正确区分什么时候用abstract,什么时候用virtual关键字。(10分)
程序不包含明显的重复性代码,逻辑清晰,代码简洁。(15分) 
计算时间的方法运行结果正确,考虑全面。(10分)
展示功能的方法可以重用,逻辑清晰简单。(10分)
*/

简单工厂

这是最入门的工厂,以它为代表的最经典表达形式就是switch 语句。我们利用一个Function工厂处理业务。我需要什么(传入标识)那么工厂就要对应的生产什么。简单的需求和生产操作。

实例Code:

/*
*以手表题目为例  
所有的手表都有自己的名字;
所有的手表都有年月日时分秒(6个属性),并且可以显示时间;
所有的手表都可以连续打出五次自己的广告语;
这三个特性是手表的最基本特性:第一条是每个手表特有的属性,第二条是公共属性。第三条也是特有的品牌属性。
*/

我们分析题目,找出公共属性并输出,这就是我们简单工厂所能实现的。我需要什么手表,我就让Watch工厂生产什么手表。
 class Watch
    {
        int watchId;
        public Watch(int watchId)
        {

            this.watchId = watchId;
            Console.WriteLine("Time Now:{0}", DateTime.Now);
        }
        /// <summary>
        /// 默认为石英表
        /// 1--电子表
        /// 2--机械表
        /// </summary>
        /// <returns></returns>
        public IProduct GetWatch()
        {
            switch (watchId)
            {
                default:
                    return new Quartz();
                case 1:
                    return new Eletronic();
                case 2:
                    return new Mechanical();
            }
        }
    }

*IWatch接口是手表输出公共属性的关键,在接口中定义ShowTime() ShowAdvertisement() ShowName()。并且所有的手表都得继承IWatch接口并实现ShowTime() ShowAdvertisement() ShowName()

*Quartz  Eletronic Mechanical这三个对象分别表示  石英  电子 机械三种手表且都继承IWatch接口。

思考问题:

假如为了业务发展扩展生产线,我要增加一万个产品。我们再增加一万个case判断,增加一万个产品对象。但是维护起来相当麻烦。此时简单工厂已经不能满足我们的需求。我们引入第二个概念工厂模式。

工厂

为了解决简单工厂生产多个产品的耦合,我们将产品线分化,分成多个子工厂。这样无论增加多少个产品,我们只需要增加产品和对应的产品工厂,避免之前的杂糅。

实例Code:

*这里以石英表对象为例子实现Demo。
*Quartz继承IWatch基本保持不变,重要的是我们把工厂对象分化,实现需求和产品族的解耦问题。
*Quartz对象实例化的时候就会显示时间,当我们GetProduct()继续执行名字和广告的显示。代码如下:

class FactoryQuartz : IFactory
    {
        IProduct Quartz;
        public FactoryQuartz()
        {
            this.Quartz = new Quartz();
        }
        public IProduct GetProduct()
        {
            Quartz.ShowName();
            Quartz.ShowAdvertisement();
            return this.Quartz;
        }
     }

public class Quartz : IWatch
    {
        public Quartz()
        {
            ShowTime();
        }
        public void ShowAdvertisement()
        {

            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine("Advertisement Eletronic Watch");
            }
        }
        public void ShowName()
        {
            Console.WriteLine("I'm Quartz Watch.");
        }
        public void ShowTime()
        {
            Console.WriteLine("Time Now:{0}", DateTime.Now);
        }
    }

interface IWatch
    {
        void ShowAdvertisement();
        void ShowName();
        void ShowTime();
    }

思考问题:
这里我们解决了需求和产品族的问题。那么我们遇到需求  品牌(产品结构) 产品族 三者关系将如何做呢。

抽象工厂

工厂模式中,一个工厂生产一个产品,所有产品派生于同一个抽象产品(或产品接口);而抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。

实例Code:

*根据课题内容,这里我们要考虑品牌因素,也就是产品结构的问题的解决。我们把工厂建立在品牌下,一个品牌一个工厂,工厂有多个生产线,生成不同的产品。如代码所示:
IFactory 接口新增多个产品Function即产品线。CreateQuartz() CreateEletronic() CreateMechanical()
class AbstractFactoryCASIO : IFactory
    {
        IProduct Eletronic;
        //IEletronic Eletronic;
        public AbstractFactoryCASIO()
        {
            this.Eletronic = new Eletronic();
        }
        public IProduct GetWatch()
        {
            Eletronic.ShowName();
            Eletronic.ShowAdvertisement();
            return this.Eletronic;
        }
       
        public IEletronic CreateEletronic()
        {
            return new AbstractElectronicCASIO();
        }
    }

*我们输出产品,首先考虑它具有产品的基本性能,即GetWatch()的实现。如题:首先是一个表,而且是一个电子表。
*其次工厂对象实现产品线的生产。然后继而表现作为卡西欧品牌特性的输出。即我们的产品。

public class Eletronic : IWatch
    {
        public Eletronic()
        {
            ShowTime();
        }
        public void ShowAdvertisement()
        {

            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine("Advertisement Eletronic Watch");
            }
        }
        public void ShowName()
        {
            Console.WriteLine("I'm Eletronic Watch");
        }
        public void ShowTime()
        {
            Console.WriteLine("Time Now:{0}", DateTime.Now);
        }
    }

1.在上面的代码中,都使用了接口来表达抽象工厂或者抽象产品,那么可以用抽象类吗?有何区别?

从功能上说,完全可以,甚至可以用接口来定义行为,用抽象类来抽象属性。抽象类更加偏向于属性的抽象,而用接口更加偏向行为的规范与统一。使用接口有更好的可扩展性和可维护性,更加灵活实现松散耦合,所以编程原则中有一条是针对接口编程而不是针对类编程。(如题还有个功能尚未实现,即手表的  年 月  日  时  分  秒 这六个属性就可以利用抽象对象来实现)

2. 到底何时应该用工厂模式

根据具体业务需求。不要认为简单工厂是用switch case就觉得一无是处,也不要觉得抽象工厂比较高大上就到处套。我们使用设计模式是为了解决问题而不是炫技,所以根据三种工厂模式的特质,以及对未来扩展的预期,来确定使用哪种工厂模式。

3.说说你在项目中工厂模式的应用

如题这就是例子,比其他的那种:“扶老奶奶过马路强多了”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值