• 设计模式工厂方法模式


    工厂方法模式:

    定义了一个创建对象的接口,但是这个类不实际生成对象的实例,而是由其子类来进行实例化.工厂方法模式让类的实例化推迟到子类.

    结构图:

    image

    解决的问题:

    在软件系统中,我们会遇到这样一个问题,我们通过某种渠道实现了某个操作后,由于需求变化,或者其他一些原因,导致这个操作需要通过另外的渠道实现,从而导致我们不得不修改这个实现方法.如何封装这样一个易变的地方.工厂方法模式不能解决修改的问题,因为需求带来的变化,导致我们可能会对代码进行改变,我们进行封装的目的是为了减少改变,即:原来修改10处,现在修改一处即可.

    使用此模式的前提是:在使用这个类的一些范围内,所有的对象都能抽象出共同的方法。

    举个例子:

    显示生活中的运输石油.我们决定使用火车运输,于是我们建立一个类,实现了以火车运输石油的方法.并且在大量的城市里都采用这种方式来运输.有一天,需求变化了,用火车运输石油导致城市严重污染,并且安全性不高,要求采用管道运输.于是我们就需要修改最初始建立的一个类,建立一个方法:输油管道().并且修改大量引用到用火车运油的地方.

    刚开始设计的类:

    public class CarryOil { public string CarryByTrain() { return "Use Train"; } }
    修改后:
    public class CarryOil { public string CarryByTrain() { return "Use Train"; } public string CarryByPiping() { return "Use Piping"; } }

    这样,如果下次要求空运,汽车运,那么该怎么处理呢?继续在CarryOil 里添加新的方法,以适应新需求的变化,这就违反了"开放封闭原则"(对扩展开放,对修改封闭),我们仔细观察这些方法,无论是采用火车、汽车、飞机、管道运输石油,都可以抽象出一个方法:运输石油。于是,我们的设计如下:

    image 

    此时,如果我们在添加新的运输方式时,只需要继承CarryOil类,实现Carry方法即可.此时,我们也无需再去关心关心其他两种运输方式是如何实现的.符合了面向对象设计中的单一职责原则,同时也很好的应用了"开放封闭原则".客户端调用时,代码如下:

    protected void Page_Load(object sender, EventArgs e) { CarryOil c = new CarryOilWithTrain(); Display(c); } void Display(CarryOil c) { Response.Write("方式:" + c.Carry() + "<hr/>"); }

    到这里,似乎设计没有问题,如果采用管道运输的话,直接改为CarryOilWithPiping即可.但是如果是页面上多处调用了上面的代码,并且都需要修改为CarryOilWithPiping时该怎么办呢?

    例如:

        protected void Page_Load(object sender, EventArgs e)
        {
            CarryOil c1 = new CarryOilWithTrain();
            Display(c1);
    
            CarryOil c2 = new CarryOilWithTrain();
            Display(c2);
    
            CarryOil c3 = new CarryOilWithTrain();
            Display(c3);
        }
    
        void Display(CarryOil c)
        {
            Response.Write("方式:" + c.Carry() + "<hr/>");
        }

    此时,如果改为使用管道运输,则3个CarryOilWithTrain都要被修改才可以.于是工厂方法模式出现了:

    image

    代码:

    public interface ITransport
    {
        CarryOil GetTraffic();
    }
    
    public class TransportWithTrain : ITransport
    {
    
        public CarryOil GetTraffic()
        {
            return new CarryOilWithTrain();
        }
    }
    
    public class TransportWithPiping : ITransport
    {
    
        public CarryOil GetTraffic()
        {
            return new CarryOilWithPiping();
        }
    }
    此时,页面调用时,如下方式调用:
        protected void Page_Load(object sender, EventArgs e)
        {
            ITransport factory = new TransportWithTrain();
    
            CarryOil c1 = factory.GetTraffic();
            Display(c1);
    
            CarryOil c2 = factory.GetTraffic();
            Display(c2);
    
            CarryOil c3 = factory.GetTraffic();
            Display(c3);
        }
    
        void Display(CarryOil c)
        {
            Response.Write("方式:" + c.Carry() + "<hr/>");
        }
    此时,如果需要修改为使用管道的话,只需要修改TransportWithTrain为TransportWithPiping即可,实现了一处修改,而不是像上面三处修改.
    而且在页面调用时,也没有使用到具体的类(这里指具体的产品类).此时是一个页面,多处调用了TransportWithTrain这个类,若是多个页面调用了这个类,该如何处理呢?
    此时可以将ITransport factory = new TransportWithTrain(); 放在一个类里,如下:
    public class CreateFactory
    {
        public CreateFactory()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }
    
        public ITransport CreateTransportFactory()
        {
            ITransport tran = new TransportWithTrain();
            return tran;
        }
    }
    页面调用时:
        protected void Page_Load(object sender, EventArgs e)
        {
            CreateFactory cf = new CreateFactory();
            ITransport factory = cf.CreateTransportFactory();
    
            CarryOil c = factory.GetTraffic();
            Display(c);
        }
    
        void Display(CarryOil c)
        {
            Response.Write("方式:" + c.Carry() + "<hr/>");
        }

    多少个页面调用这样的语句都可以,如果需要修改,使用管道时,只需要将CreateFactory类中CreateTransportFactory中的TransportWithTrain换成TransportWithPiping即可.

  • 相关阅读:
    2019春总结作业
    2019春第十二周作业
    2019春第十一周作业
    第10周作业---读后感?或许吧。
    第九周作业
    2019春第八周作业
    2019春第七周作业
    第六周作业
    2——目标与榜样
    1——自我介绍
  • 原文地址:https://www.cnblogs.com/oneword/p/1445470.html
Copyright © 2020-2023  润新知