面向对象设计模式—创建型模式(学习笔记)

学习资料

1、《设计模式:可服用面向对象软件的基础》

2、《敏捷软件开发:原则、模式与实践》

3、《重构:改善既有代码的设计》

4、《Refactoring to Patterns

5、《面向对象分析与设计》

场景

设计一个人事管理系统,其中一个功能是对不同类型的员工,计算当月的工资——不同类型的员工,拥有不同的薪金计算制度。

结构化设计

1)获得人事系统中所有可能员工类型;

2)根据不同的员工类型所对应的不同薪金制度,计算其工资。

面向对象设计

1)根据不同的员工类型设计不同的类,并使这些类继承自一个Employee抽象类,其中有一个抽象方法GetSalary

2)在不同的员工类中,根据自己的薪金制度,重写GetSalary方法。

需求改变……

场景

随着客户公司业务规模的拓展,又出现了更多类型的员工

结构化设计

几乎所有涉及到员工类型的地方都需要做改变

面向对象设计

         只需要在新的文件里添加新的员工类,让其继承自Employee抽象类,并重写GetSarary()方法,然后在EmployeeFactory.GetEmployee方法中根据相关条件,产生新的员工类型

面向对象设计三大原则:

1、针对接口编程,而不是针对实现编程;

2、优先使用对象组合(has a),而不是类继承(is a);

3、封装变化点;

使用重构得到模式——设计模式的应用不宜先入为主

五条更具体的设计原则:

1、单一职责原则(SRP

一个类应该仅有一个引起它变化的原因

2、开放封闭原则(OCP

类模块应该是可扩展的,但是不可修改(对扩展开放,对更改封闭)

3Liskov替换原则(LSP

子类必须能够替换它们的基类

4、依赖倒置原则(DIP

高层模块不应该依赖于底层模块,二者都应该依赖于抽象

抽象不应该依赖于实现细节,实现细节应该依赖于抽象

5、接口隔离原则(ISP

不应该强迫客户程序依赖于它们不用的方法

模式分类:

1、从目的看

创建型(Creational)模式:负责对象创建

结构型(Structural)模式:处理类与对象间的组合

行为性(Behavionral)模式:类与对象交互中的职责分配

2、从范围来看

类模式处理类与子类的静态关系

对象模式处理对象间的动态关系


Singleton单件(创建型模式)

1、存在的问题

         有一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性以及良好的效率——类设计者的责任,而不是使用者的责任。

2、解决思路

封装变化点:哪里变化,封装哪里

潜台词:如果没有变化,当然不需要额外的封装

3、意图

         保证一个类仅有一个实例,并提供一个该实例的全局访问点。

单线程Singleton模式的几个要点:

1Singleton模式中的实例构造器可以设置为protected以允许子类派生;

2Singleton模式一般不要支持IClonable接口;

3Singleton模式一般不要支持序列化;

4Singleton模式只考虑了对象创建的管理,没有考虑对象销毁的管理;

5Singleton模式不能用于多线程环境。

单线程Singleton模式扩展:

1、将一个实例扩展到具体的n个实例,例如对象池的实现(如Type);

2、将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的实例(如HttpContext);

3、理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。


Abstract Factory抽象工厂(创建型模式)

new的问题

1、常规的对象创建方法:Road road = new Road();

2、存在的问题

实现依赖,不能应对“具体实例化类型”的变化

3、解决思路

封装变化点:哪里变化,封装哪里

潜台词:如果没有变化,当然不需要额外的封装

工厂模式的缘起

1、变化点在“对象创建”,因此就封装“对象创建”

2面向接口编程—依赖接口而非依赖实现

3、简单工厂示例:

1)单一对象

class RoadFactory                        //--------------类库

    {

        public static Road CreateRoad()

        {

            return new Road();

        }

    }

    Road road = RoadFactory.CreateRoad();  //在其他地方实现——————客户程序

2)多个相互依赖的对象

class RoadFactory                      //--------------类库,无法实现不同风格(变化点)

    {

        public static Road CreateRoad()

        {

            return new Road();

        }

        public static Building CreateBuilding()

        {

            return new Building();

        }

        public static Tunnel CreateTunnel()

        {

            return new Tunnel();

        }

        public static Jungle CreateJungle()

        {

            return new Jungle();

        }

        ............ //创建其他对象

}

//以下代码在其他地方实现——————客户程序(相对稳定)

    Road road = RoadFactory.CreateRoad();

    Building building = RoadFactory.CreateBuilding();

............... //对象交互的代码

抽象工厂

1、存在的问题

不能应对“不同系列对象”的变化(比如不同风格的对象)

2、解决思路

使用面向对象的技术来“封装”变化点

绕过常规的对象创建方法,避免客户程序和“多系列具体对象创建”的紧耦合

提供一个接口,让该接口负责“多系列具体对象创建”而不用指定具体的类

3、意图

实现“多种相互依赖的对象”的创建工作

实现“多系列对象”的创建工作

 

4、应用要点

1)如果没有“多系列对象的构建”的需求变化,则没有必要使用Abstract Factory模式;

2)“系列对象”指的是这些对象之间有相互依赖、或作用的关系

3Abstract Factory模式主要在于应对“新系列”的需求变化,而难以应对“新对象”的需求变化;

4Abstract Factory模式经常和Factory Method模式共同组合来应对“新对象”的需求变化。


Builder 生成器(创建型模式)

Builder模式的缘起

1、假设创建游戏中的一个房屋设施(House),该房屋的构建由几个部分构成,且各个部分要富于变化;

2、如果使用最直观的设计方法,每一个房屋部分的变化,都将导致房屋构建的重新修正。

动机

1、在面临一个复杂对象的创建工作时,通常由各部分的子对象用一定的算法构成,由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法相对稳定;

2、提供一种“封装机制”来隔离出复杂对象的各个部分的变化,从而保持系统中的稳定构建算法不随着需求改变而改变;

意图

将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示

 

 

3、应用要点

1Builder模式主要用于“分步骤构建一个复杂的对象”

其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化

2)变化点在哪里,封装哪里

Builder模式用于应对“复杂对象各个部分”的需求变动,而难以应对“分步骤构建算法”的需求变动

3Abstract Factory模式解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化

Builder模式通常和Composite模式组合使用


Factory Method 工厂方法(创建型模式)

从耦合关系谈起:耦合关系直接决定着软件面对变化时的行为

模块与模块之间的紧耦合使得软件面对变化时,相关的模块都要随之更改

模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其他模块保持不变

动机

在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化使得该对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口

提供一种“封装机制”来隔离出“易变对象”的变化,从而保持系统中“其他依赖该对象的对象”不随着需求改变而改变

意图

定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而使得一个类的实例化延迟到子类

 

应用要点

1Factory Method模式主要用于隔离类对象的使用者和具体类型之间的耦合关系。

面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱

2Factory Method模式通过面向对象的手法将所要创建的具体对象延迟到子类,从而实现一种扩展的策略,较好地解决了这种紧耦合关系。

3Factory Method模式解决“单个对象”的需求变化;Abstract Factor模式解决“系列对象”的需求变化;Builder模式解决“对象部分”的需求变化。


Prototype
原型模式(创建型模式)

依赖关系的倒置

抽象不应该依赖于实现细节,实现细节依赖于抽象

动机

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作,由于需求的变化使得该对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定一致的接口

提供一种“封装机制”向客户程序隔离出“易变对象”,从而保持系统中“其他依赖这些易变对象的对象的客户程序”不随着需求改变而改变

意图

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象

 

应用要点

1Prototype原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。

2Prototype原型模式采用“原型克隆”的方式创建易变类的实体对象,从而实现灵活地动态创建“拥有某些稳定接口”的新对象。

3Prototype原型模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化方法来实现深拷贝。


有关创建型模式的讨论

1Singleton模式解决的是实体对象个数的问题,其他创建型模式解决的都是new所带来的耦合关系;

2Factory MethodAbstract FactoryBuilder都需要一个额外的工厂类来负责实例化“易变对象”, Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”;

3、如果遇到“易变对象”,起初的设计通常从Factory Method开始,当遇到更多的复杂变化时,再考虑重构为其他三种工厂模式(Abstract FactoryBuilderPrototype)。

你可能感兴趣的:(面向对象设计模式—创建型模式(学习笔记))