zoukankan      html  css  js  c++  java
  • 对象创建的依赖

    对象创建的依赖

    关于依赖的哲学,最典型的违反莫过于对象创建的依赖。自面向对象的大旗树立以来,对于对象创建话题的讨论就从未停止。不管是工厂模式还是依赖注入,其核心的思想就只有一个:如何更好地解耦对象创建的依赖关系。所以,在这一部分,我们就以对象创建为主线,来认识对于依赖关系的设计轨迹,分别论述一般的对象创建、工厂方式创建和依赖注入创建三种方式的实现、特点和区别。

    1.典型的违反

    一般而言,以new关键字进行对象创建,在.NET世界里是天经地义的事情。在本书7.1节“把new说透”中,就比较透彻地分析了new在对象创建时的作用和底层机制。对.NET程序员而言,以new进行对象创建已经是习以为常的事情,大部分情况下这种方式并没有任何问题。例如:

    public abstract class Animal

        public abstract void Show();

    }

     

    public class Dog : Animal

    {

        public override void Show()

        {

            Console.WriteLine("This is dog.");

        }

    }

     

    public class Cat : Animal

    {

        public override void Show()

        {

            Console.WriteLine("This is cat.");

        }

    }

     

    public class NormalCreation

    {

        public static void Main2()

        {

            Animal animal = new Dog();

        }

    }

    animal对象而言,大部分情况下具体的Dog类是相对稳定的,所以这种依赖很多时候是无害的。这也是我们习以为常的原因之一。

    然而,诚如在本文开始对抽象和具体的概念进行分析的结论一样,依赖于具体很多时候并不能有效地保证其稳定性的状态。以本例而言,如果有新的BirdHorse加入到动物园中来,管理员基于现有体系的管理势必不能适应形式,因为所有创建而来的实例都是依赖于Dog的。所以,普遍的对象创建方式,实际上是对DIP原则的典型违反,高层Animal的创建依赖于低层的Dog,和普世的DIP基本原则是违背的。

    因此,DIP并不是时时被OO所遵守,开发者要做的只是适度的把握。为了解决new方式创建对象的依赖违反问题,典型的解决思路是将创建的依赖由具体转移为抽象,通常情况下有两种方式来应对:工厂模式和依赖注入。

    2.工厂模式

    以工厂模式进行对象创建的方法,主要包括两种模式:抽象工厂模式和工厂方法模式,本文不想就二者的区别和意义展开细节讨论,如果有兴趣可以参阅GoF的《设计模式:可复用面向对象软件的基础》一书。

    本文将视角拉回到WCFIChannelFactory和各种Channel的创建上,以此借用WCF架构中Channel Layer的设计思路,应用工厂模式进行对象创建的设计和扩展,来了解应用工厂模式进行对象创建依赖关系解除的实质和实现。

    注意                                                                    

    对于WCFChannel的概念可以参考相关的资料,在此你只需将其看成一个简单类型即可。

    首先来了解一下Channel的创建过程:

    public class FactoryCreation

    {

        public static void Main()

        {

            EndpointAddress ea = new EndpointAddress("http://api.anytao.com /UserService");

            BasicHttpBinding binding = new BasicHttpBinding();

            IChannelFactory<IRequestChannel> facotry = binding.BuildChannelFactory<IRequestChannel>();

            facotry.Open();

            IRequestChannel channel = facotry.CreateChannel(ea);

            channel.Open();

            //Do something continue...

        }

    }

    在示例中,IRequestChannel实例通过IChannelFactory工厂来创建,因此关注工厂方式的创建焦点就着眼于IChannelFactoryIRequestChannel上。实质上,在WCF channel Layer中,Channel Factory是创建和管理Channel的工厂封装,通过一个个的Channel Factory来创建一个个对应的Channel实例,所有的Channel Factory必须继承自IChannelFactory,其定义为:

    public interface IChannelFactory<TChannel> : IChannelFactory, ICommunicationObject

    {

        TChannel CreateChannel(EndpointAddress to);

        TChannel CreateChannel(EndpointAddress to, Uri via);

    }

    通过类型参数TChannel来注册创建实例的类型信息,进而根据EndpointAddress信息来创建相应的对象实例。当然,WCF中的工厂模式应用,还有很多内容值得斟酌和学习。现有篇幅不可能实现完全类似的设计结构,借鉴于WCF的设计思路,对Animal实例的创建进行一点改造,实现基于泛型的工厂模式创建设计,首先定义一个对象创建的模板:

    public interface IAnimalFacotry<TAnimal>

    {

        TAnimal Create();

    }

    然后实现该模板的泛型工厂方法:

    public class AnimalFacotry<TAnimalBase, TAnimal> : IAnimalFacotry<TAnimalBase> where TAnimal : TAnimalBase, new()

    {

        public TAnimalBase Create()

        {

            return new TAnimal();

        }

    }

    其中类型参数TAnimalBase代表了高层类型,而TAnimal则代表了底层类型,其约定关系在where约束中有明确的定义,然后是一个基于对工厂方法的封装:

    public class FacotryBuilder

    {

        public static IAnimalFacotry<Animal> Build(string type)

        {

            if (type == "Dog")

            {

                return new AnimalFacotry<Animal, Dog>();

            }

            else if (type == "Cat")

            {

                return new AnimalFacotry<Animal, Cat>();

            }

     

            return null;

        }

    }

    最后,可以欣赏一下基于工厂方式的对象创建实现:

    class Program

    {

        static void Main(string[] args)

        {

            IAnimalFacotry<Animal> factory = FacotryBuilder.Build("Cat");

            Animal dog = factory.Create();

            dog.Show();

        }

    }

    你看,对象创建的依赖关系已经由new式的具体依赖转换为对于抽象和高层的依赖。在本例中,完全可以通过反射方式来消除if/else的运行时类型判定,从而彻底将这种依赖解除为可配置的灵活定制。这正是抽象工厂方式的伟大意义,其实在本例中完全可以将IAnimalFacotry扩展为IAnyFactory形式的灵活工厂,可以在类型参数中注册任何类型的TXXXBaseTXXX,从而实现功能更加强大的对象生成器,只不过需要更多的代码和扩展,读者可以就此进行自己的思考。

    本文节选自《你必须知道的.NET(第2版)》一书

    图书详细信息:http://www.cnblogs.com/broadview/archive/2011/08/09/2132689.html

  • 相关阅读:
    SharePoint 2013 中的SQL Server 安全
    SharePoint 2013 的HTML5特性之响应式布局
    SharePoint 2013 一些小技巧
    SharePoint 2013 排错之"Code blocks are not allowed in this file"
    SharePoint 2013 创建搜索中心及搜索设置
    SharePoint 2013 使用PowerShell创建State Service
    SharePoint 2013 内容部署功能简介
    SharePoint 使用PowerShell恢复误删的网站集
    SharePoint 自定义WebPart之间的连接
    linux之misc及使用misc创建字符设备
  • 原文地址:https://www.cnblogs.com/broadview/p/2133924.html
Copyright © 2011-2022 走看看