使用Java语言编写设计模式-章节内容合集

lingwh原创2021年7月31日大约 53 分钟约 15871 字

博客内容介绍

博客内容概述

本篇博客涉及主要内容有:
 1.设计模式引导
 2.类与类之间的六种关系
 3.设计模式七大原则
 4.创建型模式-单例模式
 5.创建型模式-简单工厂模式(Gof之外)
 6.创建型模式-工厂模式
 7.创建型模式-抽象工厂模式
 8.创建型模式-原型模式
 9.创建型模式-建造者模式
 10.结构型模式-适配器模式
 11.结构型模式-桥接模式
 12.结构型模式-装饰者模式
 13.结构型模式-组合模式
 14.结构型模式-外观模式
 15.结构型模式-享元模式
 16.结构型模式-代理模式
 17.行为型模式-模版方法模式
 18.行为型模式-命令模式
 19.行为型模式-迭代器模式
 20.行为型模式-观察者模式
 21.行为型模式-中介者模式
 22.行为型模式-备忘录模式
 23.行为型模式-解释器模式
 24.行为型模式-状态模式
 25.行为型模式-策略模式
 26.行为型模式-职责链模式
 27.行为型模式-访问者模式
具体每个章节中包含的内容可使通过下面博客内容大纲进行查看。

博客内容大纲

简单版博客内容大纲

详细版博客内容大纲

1.设计模式引导

1.1.章节内容概述

本章节涉及主要内容有:
 1.1.章节内容概述
 1.2.章节内容大纲
 1.3.设计模式起源
 1.4.设计模式是什么
 1.5.设计模式作用
 1.6.设计模式目的
 1.7.设计模式分类
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

1.2.章节内容大纲

1.3.设计模式起源

模式的概念
在介绍设计模式的起源之前,需要先介绍一个位于设计模式之上的概念,这个概念就是模式,设计模式是模式的一个分支,模式起源于建筑工程领域,最开始由是建筑工程领域提出。Christopher Alexander博士及其研究团队用了约20年的时间,对住宅和周边环境进行了大量的调查研究和资料收集工作,发现人们对舒适住宅和城市环境存在一些共同的认同规律,并在他的著作中把这些认同规律归纳为253个模式,对每一个模式(Pattern)都从Context(前提条件)、Theme或Problem(目标问题)、 Solution(解决方案)三个方面进行了描述,并给出了从用户需求分析到建筑环境结构设计直至经典实例的过程模型。在他的另一部经典著作《建筑的永恒之道》中,他给出了关于模式的定义:每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心,通过这种方式,我们可以无数次地重用那些已有的成功的解决方案,无须再重复相同的工作。这个定义可以简单地用一句话表示:模式是在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案。

Gof四人组与23中设计模式的诞生
1990年,软件工程界开始关注ChristopherAlexander等在这一住宅、公共建筑与城市规划领域的重大突破。最早将模式的思想引入软件工程方法学的是1991-1992年以"四人组(Gang of Four,简称GoF,分别是Erich Gamma, Richard Helm, Ralph Johnson和John Vlissides)"自称的四位著名软件工程学者,他们在1994年归纳发表了23种在软件开发中使用频率较高的设计模式,旨在用模式来统一沟通面向对象方法在分析、设计和实现间的鸿沟。

模式、软件模式、设计模式
GoF将模式的概念引入软件工程领域,这标志着软件模式的诞生。软件模式(Software Patterns)是将模式的一般概念应用于软件开发领域,即软件开发的总体指导思路或参照样板。软件模式并非仅限于设计模式,还包括架构模式、分析模式和过程模式等。

1.4.设计模式是什么

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。其本质是是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解,也可以说其本质是对面向对象开发的充分理解。

1.5.设计模式作用

设计模式以一种标准的方式供广大开发人员使用,为开发者的沟通提供了一套机制,帮助开发者更好地明白和更清晰地描述一段被给出的代码。

设计模式同样让开发人员之间有一套"共享词汇",一旦懂这些词汇,开发人员之间沟通这些观念就很容易,也会促使那些不懂的程序员想开始学习设计模式。

设计模式可以使开发人员更加方便简单复用成功的设计模式和结构

设计模式可以使人们深入理解面向对象的设计思想,提高软件的开发效率,节约设计成本。

1.6.设计模式目的

​ 代码重用性 相同功能的代码,不用多次编写 ​ 可读性 编程规范性,便于其他程序员的阅读和理解

​ 可扩展性 当需要增加新的功能时,非常的方便,称为可维护

​ 可靠性 当我们增加新的功能后,对原来的功能没有影响

解耦性
使程序呈现高内聚,低耦合的特性

1.7.设计模式分类

Gof提出的设计模式共23种,可以分为三种类型
创建型模式(共5种)
单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。

结构型模式(共7种)
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。

行为型模式(共11种)
模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

在Gof提出的23种设计模式之外,还有一些常用的模式
简单工厂模式/静态工厂模式

2.类与类之间的六种关系

2.1.章节内容概述

本章节涉及主要内容有:
 2.1.章节内容概述
 2.2.章节内容大纲
 2.3.依赖关系
 2.4.关联关系
 2.5.聚合关系
 2.6.组合关系
 2.7.泛化关系
 2.8.实现关系
 2.9.六种关系耦合度强弱
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

2.2.章节内容大纲

2.3.依赖关系

2.3.1.依赖关系概述

依赖关系(Dependence),只要是在类中用到了对方,那么它们之间就存在依赖关系。如果没有对方,无法通过编译。

在代码中表现为
a.类中用到了对方
b.是类的成员属性
c.是方法的返回类型
d.是方法接收的参数类型
e.方法中使用到

2.3.2.UML箭头及指向

带箭头的虚线,指向被使用者

2.3.3.依赖关系类图

2.3.4.依赖关系代码

Department.java
package com.dragonsoft.designpattern.basic.classrelation.dependence;

public class Department {
}

IDCard.java
package com.dragonsoft.designpattern.basic.classrelation.dependence;

public class IDCard {
}

Person.java
package com.dragonsoft.designpattern.basic.classrelation.dependence;

public class Person {
}

PersonDao.java
package com.dragonsoft.designpattern.basic.classrelation.dependence;

public class PersonDao {
}

PersonServiceBean.java
package com.dragonsoft.designpattern.basic.classrelation.dependence;

public class PersonServiceBean {
    private PersonDao personDao;
    public void save(Person person){}
    public IDCard getIDCard(Integer personId){
        return null;
    }
    public void modify(){
        Department department = new Department();
    }
}

2.4.关联关系

2.4.1.关联关系概述

关联关系(Association),实际上就是类与类之间的联系,它是依赖关系的特例。关联关系具有导航性:即双向关联关系或单向关联关系

2.4.2.UML箭头及指向

带普通箭头的实线,拥有者指向被拥有者

2.4.3.关联关系类图

单向关联关系
双向关联关系

2.4.4.关联关系代码

单向关联关系
Person.java
package com.dragonsoft.designpattern.basic.classrelation.association.singleone2one;
//一个人只有一个身份证,一个身份证也只能对应一个人;所以身份证跟人是一对一关系
public class Person {
    private IDCard card;
}

IDCard.java
package com.dragonsoft.designpattern.basic.classrelation.association.singleone2one;
//若果代码是这样写的话,就是单向一对一的关系。因为Person中有IDCard成员变量,而中IDCard没有Person成员变量
public class IDCard {
}

双向关联关系
Person.java
package com.dragonsoft.designpattern.basic.classrelation.association.doubleone2one;

//因为PersonIDCard中有成员变量,而中IDCard也有Person成员变量,所以这是双向一对一关系
public class Person {
    private IDCard card;
}

IDCard.java
package com.dragonsoft.designpattern.basic.classrelation.association.doubleone2one;
//因为Person中有IDCard成员变量,而中IDCard也有Person成员变量,所以这是双向一对一关系
public class IDCard {
    private Person person;
}

2.5.聚合关系

2.5.1.聚合关系概述

聚合关系(Aggregation)表示的是整体和部分的关系,整体与部分可以分开。聚合关系是关联关系的特例,所以它具有关联的导航性与多重性。

2.5.2.UML箭头及指向

带空心菱形的实心线,菱形指向整体.

2.5.3.聚合关系类图

2.5.4.聚合关系代码

Moniter.java
package com.dragonsoft.designpattern.basic.classrelation.aggregation;

public class Moniter {
}

Mouse.java
package com.dragonsoft.designpattern.basic.classrelation.aggregation;

public class Mouse {
}

Computer.java
package com.dragonsoft.designpattern.basic.classrelation.aggregation;

public class Computer {
    //显示器可以和Computer分离
    private Moniter moniter;
    //鼠标可以和Computer分离
    private Mouse mouse;

    public Moniter getMoniter() {
        return moniter;
    }

    public void setMoniter(Moniter moniter) {
        this.moniter = moniter;
    }

    public Mouse getMouse() {
        return mouse;
    }

    public void setMouse(Mouse mouse) {
        this.mouse = mouse;
    }
}

2.6.组合关系

2.6.1.组合关系概述

组合关系(Composite))表示的是整体和部分的关系,整体与部分不能分开。组合关系是关联关系的一种特例。比如说B类里面用到了一个A类,且这个A类是通过new创建的,也就是说当B类被初始化的时候A类也被初始化了。(耦合度比聚合高)

2.6.2.UML箭头及指向

带实心菱形的实线,菱形指向整体

2.6.3.组合关系类图

2.6.4.组合关系代码

Head.java
package com.dragonsoft.designpattern.basic.classrelation.composition;

public class Head {
}

Leg.java
package com.dragonsoft.designpattern.basic.classrelation.composition;

public class Leg {
}

Person.java
package com.dragonsoft.designpattern.basic.classrelation.composition;

public class Person {
    //组合关系,Person和Head是无法分开的
    private Head head = new Head();
    //组合关系,Person和Leg是无法分开的
    private Leg leg = new Leg();
}

2.7.泛化关系

2.7.1.泛化关系概述

泛化关系(Generalization),泛化关系实际上就是继承关系,它是依赖关系的特例。如果A类继承了B类,我们就说A和B存在泛化关系。

2.7.2.UML箭头及指向

带三角箭头的实线,子类指向父类

2.7.3.泛化关系类图

2.7.4.泛化关系代码

DaoSupport.java
package com.dragonsoft.designpattern.basic.classrelation.generalization;

public abstract class DaoSupport {
    public void save(Object object){}
    public void delete(Object object){}
}

PersonServiceBean.java
package com.dragonsoft.designpattern.basic.classrelation.generalization;

public class PersonServiceBean extends DaoSupport{
}

2.8.实现关系

2.8.1.实现关系概述

实现关系(Realization),比如某个类实现了一个接口。它也是依赖关系的特例。

2.8.2.UML箭头及指向

带三角箭头的虚线,箭头指向接口

2.8.3.实现关系类图

2.8.4.实现关系代码

PersonService.java
package com.dragonsoft.designpattern.basic.classrelation.realization;

public interface PersonService {
    public void delete(Integer id);
}

PersonServiceBean.java
package com.dragonsoft.designpattern.basic.classrelation.realization;

public class PersonServiceBean implements PersonService{
    @Override
    public void delete(Integer id) {

    }
}

2.9.六种关系耦合度强弱

泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖

3.设计模式七大原则

3.1.章节内容概述

本章节涉及主要内容有:
 3.1.章节内容概述
 3.2.章节内容大纲
 3.3.单一职责原则SRP
 3.4.接口隔离原则ISP
 3.5.依赖倒转原则DIP
 3.6.里氏替换原则LSP
 3.7.开闭原则OCP
 3.8.迪米特原则LoD
 3.9.合成复用原则CARP
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

3.2.章节内容大纲

3.3.单一职责原则SRP

3.3.1.单一职责原则介绍

概述
一个类应该只负责一项职责

为什么要遵循单一职责原则
如类A负责两个不同职责: 职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2。

注意事项
a.降低类的复杂度,一个类只负责一项职责
b.提高类的可读性,可维护性
c.降低变更引起的风险
d.通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则,只有类中方法数量足够少,可以在方法级别保持单一职责原则,但是通常不要违反,因为很难确定代码以后是否会发生更改

3.3.2.单一职责原则代码

3.3.2.1.不使用单一职责原则代码

package com.dragonsoft.designpattern.basic.principles.single_reponsibility;

import org.junit.Test;

/**
 * 不使用单一职能原则
 *      Vehicle1.run()方法违反了单一职能原则
 */
public class SingleReponsibility1 {
    @Test
    public void test(){
        Vehicle1 vehicle1 = new Vehicle1();
        vehicle1.run("汽车");
        vehicle1.run("火车");
        vehicle1.run("飞机");
    }
}
class Vehicle1 {
    public void run(String vehicle) {
        System.out.println(vehicle + "在公路上跑...");
    }
}

3.3.2.2.使用单一职责原则代码

3.3.2.2.1.类级别单一职责原则代码
package com.dragonsoft.designpattern.basic.principles.single_reponsibility;

import org.junit.Test;

/**
 * 类级别的单一职能原则:严格遵守了单一职责原则
 * 遵守了单一职责原则:但是会导致类大爆炸
 */
public class SingleResponsibility2 {
    @Test
    public void run(){
        RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("汽车");
        AirVehicle airVehicle = new AirVehicle();
        airVehicle.run("飞机");
        WaterVehicle waterVehicle = new WaterVehicle();
        waterVehicle.run("轮船");
    }
}

class RoadVehicle {
    public void run(String vehicle){
        System.out.println(vehicle+"在路上跑...");
    }
}

class WaterVehicle {
    public void run(String vehicle){
        System.out.println(vehicle+"在水里跑...");
    }
}

class AirVehicle {
    public void run(String vehicle){
        System.out.println(vehicle+"在天上飞...");
    }
}

3.3.2.2.2.方法别单一职责原则代码
package com.dragonsoft.designpattern.basic.principles.single_reponsibility;

import org.junit.Test;

/**
 * 方法级别的单一职能原则,会导致类中方法大爆炸
 */
public class SingleResponsibility3 {
    @Test
    public void run(){
        Veicle3 veicle3 = new Veicle3();
        veicle3.runRoad("汽车");
        veicle3.runAir("飞机");
        veicle3.runWater("轮船");
    }
}

class Veicle3 {
    public void runRoad(String vehicle){
        System.out.println(vehicle+"在路上跑...");
    }
    public void runAir(String vehicle){
        System.out.println(vehicle+"在天上飞...");
    }
    public void runWater(String vehicle){
        System.out.println(vehicle+"在水里跑...");
    }
}

3.4.接口隔离原则ISP

3.4.1.接口隔离原则介绍

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上

3.4.2.接口隔离原则代码

3.4.2.1.不使用接口隔离原则代码

Interface1.java
package com.dragonsoft.designpattern.basic.principles.interface_segregation;

/**
 * 不遵守接口隔离原则
 */
public interface Interface1 {
    void operator1();
    void operator2();
    void operator3();
    void operator4();
    void operator5();
}

/**
 * A1通过Interface1依赖B类,但只会用到1、2、3方法
 */
class A1 {
    public void depend1(Interface1 interface1){
        interface1.operator1();

        //如果不进行接口隔离,interface1仍然可以调用接口中的operator2()、operator3()、operator4()和operator5()两个方法,实际根本不需要这四个方法
        //interface1.operator2();
        //interface1.operator3();
        //interface1.operator4();
        //interface1.operator5();
    }
    public void depend2(Interface1 interface1){
        interface1.operator2();
        //如果不进行接口隔离,interface1仍然可以调用接口中的operator1()、operator3()、operator4()和operator5()两个方法,实际根本不需要这两个方法
        //interface1.operator1();
        //interface1.operator3();
        //interface1.operator4();
        //interface1.operator5();
    }
    public void depend3(Interface1 interface1){
        interface1.operator3();
        //如果不进行接口隔离,interface1仍然可以调用接口中的operator1()、operator2()、operator4()和operator5()两个方法,实际根本不需要这两个方法
        //interface1.operator1();
        //interface1.operator2();
        //interface1.operator4();
        //interface1.operator5();
    }
}
/**
 * C1通过Interface1依赖D类,但只会用到1、4、5方法
 */
class C1 {
    public void depend1(Interface1 interface1){
        interface1.operator1();

        //如果不进行接口隔离,interface1仍然可以调用接口中的operator2()、operator3()、operator4()和operator5()两个方法,实际根本不需要这四个方法
        //interface1.operator2();
        //interface1.operator3();
        //interface1.operator4();
        //interface1.operator5();
    }
    public void depend4(Interface1 interface1){
        interface1.operator4();

        //如果不进行接口隔离,interface1仍然可以调用接口中的operator1()、operator2()、operator3()和operator5()两个方法,实际根本不需要这四个方法
        //interface1.operator1();
        //interface1.operator2();
        //interface1.operator3();
        //interface1.operator5();
    }
    public void depend5(Interface1 interface1){
        interface1.operator5();

        //如果不进行接口隔离,interface1仍然可以调用接口中的operator1()、operator2()、operator3()和operator4()两个方法,实际根本不需要这四个方法
        //interface1.operator1();
        //interface1.operator2();
        //interface1.operator3();
        //interface1.operator4();
    }
}
class B1 implements Interface1 {
    @Override
    public void operator1() {
        System.out.println("B1实现了操作1...");
    }

    @Override
    public void operator2() {
        System.out.println("B1实现了操作2...");
    }

    @Override
    public void operator3() {
        System.out.println("B1实现了操作3...");
    }

    @Override
    public void operator4() {
        System.out.println("B1实现了操作4...");
    }

    @Override
    public void operator5() {
        System.out.println("B1实现了操作5...");
    }
}
class D1 implements Interface1 {
    @Override
    public void operator1() {
        System.out.println("D1实现了操作1...");
    }

    @Override
    public void operator2() {
        System.out.println("D1实现了操作2...");
    }

    @Override
    public void operator3() {
        System.out.println("D1实现了操作3...");
    }

    @Override
    public void operator4() {
        System.out.println("D1实现了操作4...");
    }

    @Override
    public void operator5() {
        System.out.println("D1实现了操作5...");
    }
}

Interface1Client.java
package com.dragonsoft.designpattern.basic.principles.interface_segregation;

import org.junit.Test;

/**
 * 调用Interface1的客户端
 */
public class Interface1Client {
    /**
     * 测试A1通过Interface1依赖B1,但是只调用1、2、3方法
     */
    @Test
    public void testA1() {
        A1 a1 = new A1();
        //本来要传入接口Interface1的,现在根据面向接口编程原则,传入Interface1的实现B1
        a1.depend1(new B1());
        a1.depend2(new B1());
        a1.depend3(new B1());
    }

    /**
     * 测试C1通过Interface1依赖D1
     */
    @Test
    public void testC1() {
        C1 c1 = new C1();
        //本来要传入接口Interface1的,现在根据面向接口编程原则,传入Interface1的实现D1
        c1.depend1(new D1());
        c1.depend4(new D1());
        c1.depend5(new D1());
    }
}

3.4.2.2.使用接口隔离原则代码

Interface2.java
package com.dragonsoft.designpattern.basic.principles.interface_segregation;

public interface Interface2 {
    void operator1();
}
/**
 * 遵循接口隔离原则
 *      把接口1差分为3个接口
 */
//public interface Interface1 {
//    void operator1();
//    void operator2();
//    void operator3();
//    void operator4();
//    void operator5();
//}
interface Interface2A {
    void operator1();
}

interface Interface2B {
    void operator2();
    void operator3();
}

interface Interface2C {
    void operator4();
    void operator5();
}

/**
 * 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
 * A2就是客户端
 * A2通过Interface1A,InterfaceC依赖B2类
 * 接口隔离后,interface2A只能调用operator1()
 *           interface2B只能调用operator2()和operator3()
 *           interface2C只能调用operator4()和operator5()
 */
class A2 {
    public void depend1(Interface2A interface2A){
        interface2A.operator1();
    }
    public void depend2(Interface2B interface2B){
        interface2B.operator2();
    }
    public void depend3(Interface2B interface2B){
        interface2B.operator3();
    }
}

/**
 * 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
 * C2就是客户端
 * C2通过Interface2A,Interface2B依赖D2类
 * 接口隔离后,interface2A只能调用operator1()
 *            interface2B只能调用operator2()和operator3()
 *            interface2C只能调用operator4()和operator5()
 */
class C2 {
    public void depend1(Interface2A interface2A){
        interface2A.operator1();
    }
    public void depend4(Interface2C interface2C){
        interface2C.operator4();
    }
    public void depend5(Interface2C interface2C){
        interface2C.operator5();
    }
}

class B2 implements Interface2A,Interface2B {
    @Override
    public void operator1() {
        System.out.println("B2实现了操作1...");
    }

    @Override
    public void operator2() {
        System.out.println("B2实现了操作2...");
    }

    @Override
    public void operator3() {
        System.out.println("B2实现了操作3...");
    }
}

class D2 implements Interface2A,Interface2C {
    @Override
    public void operator1() {
        System.out.println("D2实现了操作1...");
    }

    @Override
    public void operator4() {
        System.out.println("D2实现了操作4...");
    }

    @Override
    public void operator5() {
        System.out.println("D2实现了操作5...");
    }
}


Interface2Client.java
package com.dragonsoft.designpattern.basic.principles.interface_segregation;

import org.junit.Test;

public class Interface2Client {
    /**
     * 测试A2通过接口Interface2A,Interface2B依赖B2
     */
    @Test
    public void testA2() {
        A2 a2 = new A2();
        a2.depend1(new B2());
        a2.depend2(new B2());
        a2.depend3(new B2());
    }

    /**
     * 测试C2通过接口Interface2B,Interface2C依赖D2
     */
    @Test
    public void testC2() {
        C2 c2 = new C2();
        c2.depend1(new D2());
        c2.depend4(new D2());
        c2.depend5(new D2());
    }
}

3.5.依赖倒转原则DIP

3.5.1.依赖倒转原则介绍

概述
a.高层模块不应该依赖底层模块,二者都应该依赖其抽象
b.抽象不应该依赖细节,细节应该依赖抽象
c.依赖反转的中心思想是面向结构编程
d.依赖反转的思想是基于这样的理念:相对于细节的多变性,抽象的东西要稳定的多,以抽象为基础的架构比以细节为基础的架构要稳定的多,在java中,抽象的多指接口和抽象类,细节就是具体的实现类
e.使用类或者接口的目的是制定规范,而不涉及任何具体的子类操作,把展现细节的任务交给他们的实现类去做

依赖关系传递的三种方式
a.接口传递
b.构造方法传递
c.setter方法传递

注意事项
a.底层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好
b.变量的声明类型尽量都是抽象类或者接口,这样我们的变量引用和实际对象之间,就存在一个缓冲层,有利于程序的优化和扩展
c.继承是遵循里氏替换原则

3.5.2.依赖倒转原则代码

3.5.2.1.不使用依赖倒转原则代码

package com.dragonsoft.designpattern.basic.principles.dependenceinversion;

/**
 * 不使用依赖反转原则
 */
public class NoUseDependenceDeliverTest {
    public static void main(String[] args) {
        Person1 person1 = new Person1();
        person1.receviceEmail(new Email1());
        person1.receviceQQ(new QQ1());
        person1.receviceWeChat(new WeChat1());
    }
}

/**
 * 通过Person1实现接口消息的功能
 *      缺点:接受QQ要写一个方法,接收邮件要写一个方法
 */
class Person1{
    public void receviceEmail(Email1 email1){
        System.out.println(email1.getEmail());
    }
    public void receviceQQ(QQ1 qq1){
        System.out.println(qq1.getQQ());
    }
    public void receviceWeChat(WeChat1 weChat){
        System.out.println(weChat.getWeChat());
    }
}
class Email1 {
   public String getEmail(){
        return "电子邮件信息:HelloWorld";
   }
}
class QQ1 {
   public String getQQ(){
        return "QQ信息:收到了QQ消息";
   }
}
class WeChat1 {
    public String getWeChat(){
        return "微信信息:收到了微信消息";
    }
}


3.5.2.2.使用依赖倒转原则代码

3.5.2.2.1.依赖倒转原则简单案例
package com.dragonsoft.designpattern.basic.principles.dependenceinversion;

/**
 * 遵循依赖反转原则
 * 面向接口编程
 *      基于接口传递实现依赖
 */
public class UseDependenceDeliverTest {
    public static void main(String[] args) {
        //面向接口编程
        Person2 person2 = new Person2();
        person2.getMessage(new Email2());
        person2.getMessage(new QQ2());
        person2.getMessage(new WeChat2());
    }

}

class Person2 {
    public void getMessage(MessageInterface messageInterface) {
        System.out.println(messageInterface.sendMessage());
    }
}

interface MessageInterface {
    String sendMessage();
}

class Email2 implements MessageInterface{
    @Override
    public String sendMessage() {
        return  "电子邮件信息:HelloWorld";
    }
}

class QQ2 implements MessageInterface{
    @Override
    public String sendMessage() {
        return "QQ信息:收到了QQ消息";
    }
}
class WeChat2 implements MessageInterface{
    @Override
    public String sendMessage(){
        return "微信信息:收到了微信消息";
    }
}

3.5.2.2.2.通过接口传递依赖
package com.dragonsoft.designpattern.basic.principles.dependenceinversion;

/**
 * 依赖关系传递的三种方式
 *  第一种方式:通过接口传递依赖
 */
public class DependenceDeliver1 {
    public static void main(String[] args) {
        OpenAndClose1 openAndClose1 = new OpenAndClose1();
        openAndClose1.open(new ITV1() {
            @Override
            public void play() {
                System.out.println("ITV1播放......");
            }
        });
    }
}

interface ITV1{
    public void play();
}
interface IOpenAndClose1{
    public void open(ITV1 iTv1);
}
class OpenAndClose1 implements IOpenAndClose1{

    @Override
    public void open(ITV1 iTv1) {
        iTv1.play();
    }
}

3.5.2.2.3.通过构造方法传递依赖
package com.dragonsoft.designpattern.basic.principles.dependenceinversion;

/**
 * 依赖关系传递的三种方式
 *  第二种方式:通过构造方法传递依赖
 */
public class DependenceDeliver2 {
    public static void main(String[] args) {
        OpenAndClose2 openAndClose2 = new OpenAndClose2(new ITV2() {
            @Override
            public void play() {
                System.out.println("ITV2播放......");
            }
        });
        openAndClose2.open();
    }
}

interface ITV2{
    public void play();
}

interface IOpenAndClose2{
    public void open();
}

class OpenAndClose2 implements IOpenAndClose2{

    public ITV2 iTv2;
    public OpenAndClose2(ITV2 iTv2) {
        this.iTv2 = iTv2;
    }

    @Override
    public void open() {
        this.iTv2.play();
    }
}

3.5.2.2.4.通过setter()方法传递依赖
package com.dragonsoft.designpattern.basic.principles.dependenceinversion;

/**
 * 依赖关系传递的三种方式
 *  第三种方式:通过setter()方法传递依赖
 */
public class DependenceDeliver3 {
    public static void main(String[] args) {
        OpenAndClose3 openAndClose3 = new OpenAndClose3();
        openAndClose3.setItv3(new ITV3() {
            @Override
            public void play() {
                System.out.println("ITV3播放......");
            }
        });
        openAndClose3.open();
    }
}

interface ITV3{
    public void play();
}

interface IOpenAndClose3 {
    public void open();
}

class OpenAndClose3 implements IOpenAndClose3{

    private ITV3 itv3;

    public void setItv3(ITV3 itv3) {
        this.itv3 = itv3;
    }

    @Override
    public void open() {
        this.itv3.play();
    }
}

3.6.里氏替换原则LSP

3.6.1.里氏替换原则介绍

概述
里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合、组合、依赖来解决问题

里氏替换原则是为了解决了什么问题
a.正确的使用继承
b.将原来的继承关系转换为继承基类+聚合/组合/依赖关系

里氏替换原则详细说明
a.所有能使用父类的地方,都能透明的使用该父类的子类对象
即继承时,子类尽量不要重写父类的方法,除非迫不得已,如果非要重写,就再写一个更基础的类,把这个要重写的方法提到基类里面去
b.遵循里氏替换原则,把继承这种高耦合的关系转换为聚合、组合、依赖这几种低耦合的关系

3.6.2.里氏替换原则代码

3.6.2.1.不使用里氏替换原则代码

package com.dragonsoft.designpattern.basic.principles.liskov_substitution;

/**
 * 未使用里氏替换原则
 * B1类继承了A1类,在不知道的情况下重下了父类A1的fun1()方法,外部调用子类B1类中中fun1()的时候以为
 *      里面的逻辑还是a-b,其实逻辑已经在不知道的情况下被重写成a+b了,导致计算结果出了问题
 *
 * 缺点:A1和B1的耦合性太高了,修改B很容易对A造成影响
 */
public class Liskov1 {
    public static void main(String[] args) {
        A1 a1 = new A1();
        System.out.println("11-3 = "+a1.fun1(11,3));
        System.out.println("1-8 = "+a1.fun1(1,8));

        A1 b1 = new B1();
        System.out.println("11-3 = "+b1.fun1(11,3));
        System.out.println("1-8 = "+b1.fun1(1,8));

    }
}

class A1 {
    /**
     * 返回 a与b的差
     * @param a
     * @param b
     * @return
     */
    public int fun1(int a,int b){
        return a-b;
    }

    public void printHelloWorld(){
        System.out.println("Hello World!");
    }
}

/**
 * B1类继承了A1类,在不知道的情况下重下了父类A的fun1()方法
 */
class B1 extends A1 {

    /**
     * 返回 a与b的和
     * @param a
     * @param b
     * @return
     */
    public int fun1(int a,int b){
        return a+b;
    }

    /**
     * B1独有方法,非继承自A1
     * 返回 a与b的和加上9
     * @param a
     * @param b
     * @return
     */
    public int fun2(int a,int b){
        return fun1(a,b) + 9;
    }

    public void printHelloWorld(){
        System.out.println("Hello World!");
    }
}

3.6.2.2.使用里氏替换原则代码

package com.dragonsoft.designpattern.basic.principles.liskov_substitution;

/**
 * 使用里氏替换原则:
 *  1.B2类不再继承A2类,改为A2类和B2类都继承一个基类Base
 *  2.这样调用者通过查看继承关系,明显的就知道了B2类中的fun1()里面的逻辑是a+b,而不是a-b
 *  3.把A2和B2中的公用方法printHelloWorld()抽取到了Base中
 *
 *  注意:本来B2继承了A2,可以直接调用父类A2中的方法,里氏替换原则修改代码后,B2不再继承A2,B2想要调用A2中的方法则可以通过依赖A2来实现调用
 */
public class Liskov2 {
    /**
     * 将A2和B2中的公用方法printHelloWorld()抽取到了Base中
     */
    public void printHelloWorld(){
        System.out.println("Hello World!");
    }
}


class Base{
    //把更加基础的方法和成员写到Base类中
}
class A2 extends Base{
    /**
     * 返回 a与b的差
     * @param a
     * @param b
     * @return
     */
    public int fun1(int a,int b){
        return a-b;
    }
}

class B2 extends Base {

    //B通过这个方式依赖A
    private A2 a2 = new A2();

    /**
     * 返回 a与b的和
     * @param a
     * @param b
     * @return
     */
    public int fun1(int a,int b){
        return a+b;
    }

    /**
     * B2独有方法,非继承自A2
     * 返回 a与b的和加上9
     * @param a
     * @param b
     * @return
     */
    public int fun2(int a,int b){
        return fun1(a,b) + 9;
    }

    /**
     * 里氏替换原则,如果B2和A2同时继承了基类Base,那么当B2想要使用A2类中的方法的时候,可以通过依赖的方式来调用A类2中的方法
     * @param a
     * @param b
     * @return
     */
    public  int fun3(int a,int b){
        return this.a2.fun1(a,b);
    }
}

3.7.开闭原则OCP

3.7.1.开闭原则介绍

概述
对修改关闭,对扩展开放

开闭原则详细说明
a.开闭原则是编程中最基础,最为重要的原则
b.一个软件实体,函数模块应该对扩展开放(对提供功能的一方而言),对修改关闭(对调用方/使用功能的一方而言,注意:不是对于客户端开放,客户端调用方法的使用方)。换而言之,当当增加一个新的类或者方法后,原先正在使用的代码不会收到丝毫影响,概括的说:对扩展开放,对修改关闭,即用抽象构建框架,用实现扩展细节
c.当软件需要变化时,尽量通过扩展软件的实体行为来实现变化,而不是通过修改已有的代码去实现,简单的说,就是通过扩展而不是通过修改已有代码
d.使用设计模式就是为了使代码更遵守开闭原则,是最重要的原则,其他的设计模式都是为了达到开闭原则的效果
e.遵循OPC原则设计出来的系统意味着具有相当的稳定性,至少在增加新功能的时候不会影响旧的功能,因为新的功能是通过扩展原来功能,而不是修改原来的功能,在代码层面的体现是新增一个功能不会动原来的代码,而是把新的功能写在新的类中

3.7.2.开闭原则代码

3.7.2.1.不使用开闭原则代码

package com.dragonsoft.designpattern.basic.principles.open_close;

/**
 * 不遵循OCP原则,目前只有一个画三角形的需求,当增加一个画圆形的需求的时候,
 * 不仅要对方法的提供者Painter做修改,也要对调用者做修改
 *
 */
public class OCPTest1 {
    public static void main(String[] args) {
        Painter1 painter1 = new Painter1();
        painter1.drawShape(new Triagle1());
        painter1.drawShape(new Cricle1());
    }
}
/**
 * 方法的使用方:
 *      不遵守OCP,扩展的时候要对方法的使用方做修改
 */
class Painter1 {
    public void drawShape(Shape1 shape){
        if(shape.type == 1) {
            drawTriangle();
        }else if(shape.type == 2) {
            drawCircle();
        }
    }
    private void drawTriangle(){
        System.out.println("画三角形...");
    }
    private void drawCircle(){
        System.out.println("画圆形...");
    }
}
class Shape1 {
    public int type;
}

/**
 * 方法的提供方
 */
class Triagle1 extends Shape1{
    public Triagle1(){
        super.type = 1;
    }
}
/**
 * 方法的提供方
 */
class Cricle1 extends Shape1{
    public Cricle1(){
        super.type = 2;
    }
}

3.7.2.2.使用开闭原则代码

package com.dragonsoft.designpattern.basic.principles.open_close;

public class OCPTest2 {
    public static void main(String[] args) {
        Painter2 painter2 = new Painter2();
        painter2.drawShape(new Triagle2());
        painter2.drawShape(new Cricle2());
    }
}

/**
 * 方法的使用方:
 *      遵守OCP,扩展的时候不用再对方法的使用方做修改
 */
class Painter2 {
    public void drawShape(Shape2 shape){
       shape.draw();
    }
}
abstract class Shape2 {
    public int type;
    public abstract void draw();
}
/**
 * 方法的提供方
 */
class Triagle2 extends Shape2{
    public Triagle2(){
        super.type = 1;
    }

    @Override
    public void draw() {
        System.out.println("画三角形......");
    }
}
/**
 * 方法的提供方
 */
class Cricle2 extends Shape2{
    public Cricle2(){
        super.type = 2;
    }

    @Override
    public void draw() {
        System.out.println("画圆形......");
    }
}

3.8.迪米特原则LoD

3.8.1.迪米特原则介绍

概述
只与直接的朋友通信,最少知道原则,避免与非直接朋友的耦合,对自己依赖的类知道的越少越好,对于被依赖的类不管多复杂,都尽量将逻辑封在内部。需要注意的是降低类之间的耦合,只是减少不必要的耦合,并不是要求完全解除耦合

迪米特原则详细说明
a.一个对象应该对其他对象保持最少的了解
b.类与类关系越密切,耦合度越大
c.迪米特原则又称最少知道原则,即一个类对自己依赖的类知道的越少越好,也就是说,对于被依赖的类不管多么复杂,都应该尽量将逻辑封装在类的内部,除了对外提供public方法之外,不对外泄露任何信息
e.迪米特方法还有个更简单的定义: 只与直接朋友通信
    直接朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就直接说这两个对象之间是朋友关系。耦合的方式有很多依赖、关联、组合、聚合,其中我们将出现在成员变量,方法参数,方法返回值这几个位置中类称为直接朋友,而出现在局部变量中的类不是直接朋友,也就是说,陌生的类最好不要以局部变量的方式出现在类的内部

直接朋友和间接朋友
直接朋友:出现在返回值、成员变量、方法参数中的类
间接朋友:出现在方法中作为局部变量的类
class A{
    public void fun(){}
}
class C{
    public void fun(){}
}
class B{
    //C就是B的直接朋友:出现在成员变量位置
    private C c = new C();
    //C就是B的直接朋友:出现在方法参数位置
    public void test1(C c){
        c.fun();
    }
    //C就是B的直接朋友:出现在返回值位置
    public C test3(){
        return null;
    }
    public void test4(){
        //A就是B的间接朋友:出现在方法中作为局部变量位置
        A a = new A();
        a.fun();
    }
}

3.8.2.迪米特原则代码

3.8.2.1.不使用迪米特原则代码

package com.dragonsoft.designpattern.basic.principles.demeter;

import java.util.ArrayList;
import java.util.List;

/**
 * 未遵守迪米特法则
 */
public class Demeter1 {
    public static void main(String[] args) {
        SchoolManager1 schoolManager1 = new SchoolManager1();
        schoolManager1.printAllEmployee(new CollegeManager1());
    }
}

/**
 * 学校总部员工类
 */
class Employee1 {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

/**
 * 学院员工类
 */
class CollegeEmployee1 {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

/**
 * 学院员工管理类
 */
class CollegeManager1 {
    public List<CollegeEmployee1> getAllCollegeEmployee(){
        List<CollegeEmployee1> list = new ArrayList<CollegeEmployee1>();
        //增加10个员工到学院
        for(int i=0; i<10; i++){
            CollegeEmployee1 collegeEmployee = new CollegeEmployee1();
            collegeEmployee.setId("学院员工id" + i);
            list.add(collegeEmployee);
        }
        return list;
    }
}

/**
 * 学校总部员工管理类
 *  SchoolManager的直接朋友:Employee、CollegeManager
 *  SchoolManager的非直接朋友:CollegeEmployee,这样就 违反了迪米特法则(只与直接的朋友通信,最少知道原则,避免与非直接朋友的耦合)
 */
class SchoolManager1 {
    public List<Employee1> getAllEmployee(){
        List<Employee1> list = new ArrayList<Employee1>();
        //增加5个员工到学校总部
        for(int i=0; i<5; i++){
            Employee1 employee1 = new Employee1();
            employee1.setId("学校总部员工id" + i);
            list.add(employee1);
        }
        return list;
    }

    /**
     * 输出学校总部和学院员工信息
     * @param collegeManager1
     */
    public void printAllEmployee(CollegeManager1 collegeManager1){
        List<CollegeEmployee1> allCollegeEmployee = collegeManager1.getAllCollegeEmployee();
        System.out.println("--------------学院员工--------------");
        for (CollegeEmployee1 collegeEmployee1 : allCollegeEmployee) {
            System.out.println(collegeEmployee1.getId());
        }

        List<Employee1> allEmployee = this.getAllEmployee();
        System.out.println("--------------学校总部员工--------------");
        for (Employee1 employee1 : allEmployee) {
            System.out.println(employee1.getId());
        }
    }
}

3.8.2.2.使用迪米特原则代码

package com.dragonsoft.designpattern.basic.principles.demeter;

import java.util.ArrayList;
import java.util.List;

/**
 * 使用迪米特法则改进
 */
public class Demeter2 {
    public static void main(String[] args) {
        SchoolManager2 schoolManager2 = new SchoolManager2();
        schoolManager2.printAllEmployee(new CollegeManager2());
    }
}

/**
 * 学校总部员工类
 */
class Employee2 {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

/**
 * 学院员工类
 */
class CollegeEmployee2 {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

/**
 * 学院员工管理类
 */
class CollegeManager2 {
    public List<CollegeEmployee2> getAllCollegeEmployee(){
        List<CollegeEmployee2> list = new ArrayList<CollegeEmployee2>();
        //增加10个员工到学院
        for(int i=0; i<10; i++){
            CollegeEmployee2 collegeEmployee2 = new CollegeEmployee2();
            collegeEmployee2.setId("学院员工id" + i);
            list.add(collegeEmployee2);
        }
        return list;
    }
    /**
     * 输出学院员工信息
     * @param
     */
    public void printAllEmployee() {
        List<CollegeEmployee2> allCollegeEmployee = this.getAllCollegeEmployee();
        System.out.println("--------------学院员工--------------");
        for (CollegeEmployee2 collegeEmployee2 : allCollegeEmployee) {
            System.out.println(collegeEmployee2.getId());
        }
    }
}

/**
 * 学校总部员工管理类
 */
class SchoolManager2 {
    public List<Employee2> getAllEmployee(){
        List<Employee2> list = new ArrayList<Employee2>();
        //增加5个员工到学校总部
        for(int i=0; i<5; i++){
            Employee2 employee2 = new Employee2();
            employee2.setId("学校总部员工id" + i);
            list.add(employee2);
        }
        return list;
    }

    /**
     * 输出学校总部员工信息
     * @param collegeManager2
     */
    public void printAllEmployee(CollegeManager2 collegeManager2){
        //输出学院员工信息
        collegeManager2.printAllEmployee();

        //输出学校员工信息
        List<Employee2> allEmployee = this.getAllEmployee();
        System.out.println("--------------学校总部员工--------------");
        for (Employee2 employee2 : allEmployee) {
            System.out.println(employee2.getId());
        }

    }
}

3.9.合成复用原则CARP

3.9.1.合成复用原则介绍

概述
尽量使用合成/聚合方法,避免使用继承

使用合成复用原则有什么效果
当A继承B后,A拥有B所有的方法,使用合成复用改进后,A可以调用B中的方法,不用的方法就不出现在B中了

合成复用原则与继承原则关系
在编程中,推荐尽量使用合成复用原则来代替继承,但是反过来,可以使用合成复用原则解决的问题也可以使用继承解决

3.9.2.合成复用原则代码

3.9.2.1.不使用合成复用原则代码

package com.dragonsoft.designpattern.basic.principles.compositereuse;

/**
 * 合成复用原则
 */
public class CompositeReuse1 {
}

/**
 * 继承关系
 * 如果想让B1使用A1的方法,可以让B1继承A1,不过,这样会加重B1和A1的耦合
 */
class A1{
    public void fun1(){}
    public void fun2(){}
    public void fun3(){}
}

class B1 extends A1 {

}

3.9.2.2.使用合成复用原则代码

package com.dragonsoft.designpattern.basic.principles.compositereuse;

/**
 * 合成复用原则
 */
public class CompositeReuse2 {
}

/**
 * 代替继承关系的方式一:依赖关系
 * 如果想让B1使用A1的方法,B2依赖A2,即在B2的方法参数中传入A2,然后再通过调用A2对象的方法来实现B2使用A2中的方法
 */
class A2{
    public void fun1(){}
    public void fun2(){}
    public void fun3(){}
}

class B2{
    public void fun1(A2 a2){
        a2.fun1();
    }
    public void fun2(A2 a2){
        a2.fun2();
    }
    public void fun3(A2 a2){
        a2.fun3();
    }
}

/**
 * 代替继承关系的方式二:聚合关系
 * 把A3聚合到B3中,即A3作为B3的属性出现在B3中,并且通过setter()方法为B3中的A3注入值
 */
class A3{
    public void fun1(){}
    public void fun2(){}
    public void fun3(){}
}

class B3{
    private A3 a3;

    public void setA3(A3 a3) {
        this.a3 = a3;
    }

    public void fun1(){
        a3.fun1();
    }
    public void fun2(){
        a3.fun2();
    }
    public void fun3(){
        a3.fun3();
    }
}

/**
 * 代替继承关系的方式三:组合关系
 * 让A4作为B4的属性出现在B4中,而且当B4创建完成后A4就创建完成了,称为把A4组合到B4中
 * 让A4作为B5的属性出现在B5中,而且当B5创建完成后A4就创建完成了,称为把A5组合到B4中
 */
class A4{
    public void fun1(){}
    public void fun2(){}
    public void fun3(){}
}
//通过直接new给成员变量赋值
class B4{
    private A4 a4 = new A4();

    public void fun1(){
        a4.fun1();
    }
    public void fun2(){
        a4.fun2();
    }
    public void fun3(){
        a4.fun3();
    }
}
//通过构造方法给成员变量赋值
class B5{
    private A4 a4;
    public B5(A4 a4){
        this.a4 = a4;
    }

    public void fun1(){
        a4.fun1();
    }
    public void fun2(){
        a4.fun2();
    }
    public void fun3(){
        a4.fun3();
    }
}

4.创建型模式-单例模式

4.1.章节内容概述

本章节涉及主要内容有:
 4.1.章节内容概述
 4.2.章节内容大纲
 4.3.简介
 4.4.应用场景
 4.5.优缺点
 4.6.角色及其职责
 4.7.模型
 4.8.示例
 4.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

4.2.章节内容大纲

4.3.简介

单例模式(Singleton Pattern)是一种创建型设计模式,又名单件模式或单态模式,目的是为了保证一个类只有一个实例对象,并提供一个获取该实例对象的全局方法,通过这个全局方法创建的所有实例对象都是同一个实例对象,这个类称为单例类。单例模式的要点有三个:一是某个类只能有一个实例对象;二是这个类必须自行创建这个实例对象;三是这个类必须自行向整个系统提供这个实例。

4.4.应用场景

单例模式应用的场景一般发现在以下条件下
资源共享的情况下: 避免由于资源操作时导致的性能或损耗等
控制资源的情况下: 方便资源之间的互相通信

具体应用场景
a.Windows的Task Manager(任务管理器),在一个Windows系统中只有一个Task Manager实例
b.Windows的Recycle Bin(回收站),在一个Windows系统中只有一个Recycle Bin实例
c.网站的计数器,一般也是采用单例模式实现,否则难以同步
d.应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则无法实现内容追加
e.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗
f.多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制
g.操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统

4.5.优缺点

4.5.1.优点

a.由于单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了
b.由于单例模式只生成一个实例,所以,减少系统的性能开销,当一个对象产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
c.单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作
d.单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如,可以设计一个单例类,负责所有数据表的映射处理

4.5.2.缺点

a.单例模式没有抽象层,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现,违反了OCP原则
b.单例类的职责过重,在一定程度上违背了"单一职责原则"
c.滥用单例将带来一些负面问题,如:为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出

4.6.角色及其职责

4.7.模型

4.7.1.模型类图

类图(有Client)
类图(无Client)

4.7.2.代码

package com.dragonsoft.designpattern.create.singleton.model;

public class SingletonObject {
    private SingletonObject() {}
    private static final SingletonObject SINGLETON_INSTANCE = new SingletonObject();
    public static SingletonObject getInstance() {
        return SINGLETON_INSTANCE;
    }
    public void operate(){
        System.out.println("do some operate......");
    }
}

4.8.示例

4.8.1.饿汉式单例

4.8.1.1.类图

类图(有Client)
类图(无Client)

4.8.1.2.代码

SingletonA.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 饿汉式
 * @author lingwh
 *
 */
public class SingletonA {
    private SingletonA() {}
    private static final SingletonA SINGLETONA = new SingletonA();
    public static SingletonA getInstance() {
        return SINGLETONA;
    }
}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
	/**
	 * 测试测试饿汉式单例
	 */
	@Test
	public void fun() {
		SingletonA instance1 = SingletonA.getInstance();
		SingletonA instance2 = SingletonA.getInstance();
		System.out.println(instance1 == instance2);
		System.out.println("instance1.hashCode():"+instance1.hashCode());
		System.out.println("instance2.hashCode():"+instance2.hashCode());
	}
}

4.8.2.懒汉式单例

4.8.2.1.饿汉式单例类图

类图(有Client)
类图(无Client)

4.8.2.2.代码

SingletonB.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 懒汉式:
 * 	优点:可以实现懒加载
 * 	缺点:有线程安全问题
 * @author lingwh
 *
 */
public class SingletonB {
    private SingletonB() {}
    private static SingletonB singletonB = null;
    public static SingletonB getInstance() {
        if(singletonB == null) {
            singletonB = new SingletonB();
        }
        return singletonB;
    }
}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
	/**
	 * 测试单线程测试懒汉式
	 */
	@Test
	public void fun1() {
		SingletonB instance1 = SingletonB.getInstance();
		SingletonB instance2 = SingletonB.getInstance();
		System.out.println(instance1 == instance2);
		System.out.println("instance1.hashCode():"+instance1.hashCode());
		System.out.println("instance2.hashCode():"+instance2.hashCode());
	}

	/**
	 * 测试多线程测试线程不安全的懒汉式
	 */
	@Test
	public void fun2() {
		long begin = System.currentTimeMillis();
		//多线程测试单例模式线程是否安全
		Thread[] threads = new Thread[10000];
        for(int i = 0;i<threads.length;i++){
        	//创建线程
        	threads[i] =
				new Thread(new Runnable() {
	    			@Override
	    			public void run() {
	    				SingletonB instance = SingletonB.getInstance();
	    				System.out.println("instance.hashCode():"+instance.hashCode());
	    			}
	    		});
        }
        for(int i=0;i<threads.length;i++){
        	threads[i].start();//线程启动
        }
        long end = System.currentTimeMillis();
        System.out.println("程序执行时间:" + (end-begin));
	}
}

4.8.3.线程安全的懒汉式单例

4.8.3.1.类图

类图(有Client)
类图(无Client)

4.8.3.2.代码

SingletonC.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 线程安全的懒汉式
 * @author lingwh
 *
 */
public class SingletonC {
    private SingletonC() {}
    private static SingletonC singletonC;
    public static synchronized SingletonC getInstance() {
        if(singletonC == null) {
            singletonC = new SingletonC();
        }
        return singletonC;
    }
}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
	/**
	 * 测试多线程测试线程安全的懒汉式
	 * 	方法级别的锁:实测执行效率并不是很低
	 */
	@Test
	public void fun() {
		long begin = System.currentTimeMillis();
		//多线程测试单例模式线程是否安全
		Thread[] threads = new Thread[10000];
		for(int i = 0;i<threads.length;i++){
			//创建线程
			threads[i] =
					new Thread(new Runnable() {
						@Override
						public void run() {
							SingletonC instance = SingletonC.getInstance();
							System.out.println("instance.hashCode():"+instance.hashCode());
						}
					});
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();//线程启动
		}
		long end = System.currentTimeMillis();
		System.out.println("程序执行时间:" + (end-begin));
	}
}

4.8.4.双重检索懒汉式懒汉式单例

4.8.4.1.类图

类图(有Client)
类图(无Client)

4.8.4.2.代码

SingletonD.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 双重检索懒汉式
 * @author lingwh
 *
 */
public class SingletonD {
    private SingletonD() {}
    private static volatile SingletonD singletonD;
    public static SingletonD getInstance() {
        if(singletonD == null) {
            synchronized(SingletonD.class) {
                if(singletonD == null) {
                    singletonD = new SingletonD();
                }
            }
        }
        return singletonD;
    }
}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
    /**
	 * 测试多线程测试静态双重检索线程安全的懒汉式
	 * 	方法级别的锁:实测执行效率并不是很低
	 */
	@Test
	public void fun() {
		long begin = System.currentTimeMillis();
		//多线程测试单例模式线程是否安全
		Thread[] threads = new Thread[10000];
		for(int i = 0;i<threads.length;i++){
			//创建线程
			threads[i] =
					new Thread(new Runnable() {
						@Override
						public void run() {
							SingletonD instance = SingletonD.getInstance();
							System.out.println("instance.hashCode():"+instance.hashCode());
						}
					});
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();//线程启动
		}
		long end = System.currentTimeMillis();
		System.out.println("程序执行时间:" + (end-begin));
	}
}

4.8.5.静态内部类懒汉式单例

4.8.5.1.类图

类图(有Client)
类图(无Client)

4.8.5.2.代码

SingletonE.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 静态内部类懒汉式
 * 	原理:JVM在装载类的时候是线程安全的
 * @author lingwh
 *
 */
public class SingletonE {
    private SingletonE() {}
    public static SingletonE getInstance() {
        return SingletonInstacne.INSTANCE;
    }
    private static class SingletonInstacne {
        private static final SingletonE INSTANCE = new SingletonE();
    }
}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
    /**
	 * 测试多线程测试静态内部类线程安全的懒汉式
	 */
	@Test
	public void fun() {
		long begin = System.currentTimeMillis();
		//多线程测试单例模式线程是否安全
		Thread[] threads = new Thread[10000];
		for(int i = 0;i<threads.length;i++){
			//创建线程
			threads[i] =
					new Thread(new Runnable() {
						@Override
						public void run() {
							SingletonE instance = SingletonE.getInstance();
							System.out.println("instance.hashCode():"+instance.hashCode());
						}
					});
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();//线程启动
		}
		long end = System.currentTimeMillis();
		System.out.println("程序执行时间:" + (end-begin));
	}
}

4.8.6.枚举单例

4.8.6.1.类图

类图(有Client)
类图(无Client)

4.8.6.2.代码

SingletonF.java
package com.dragonsoft.designpattern.create.singleton;

/**
 * 枚举实现单例
 * @author lingwh
 *
 */
public enum SingletonF {
    INSTANCE;
    public void doSomething() {
        System.out.println("doSomething......");
    }

}

Client.java
package com.dragonsoft.designpattern.create.singleton;

import org.junit.Test;

public class Client {
    /**
	 * 测试枚举实现单例
	 */
	@Test
	public void fun() {
		SingletonF instance1 = SingletonF.INSTANCE;
		SingletonF instance2 = SingletonF.INSTANCE;
		System.out.println(instance1 == instance2);
		System.out.println("instance1.hashCode():"+instance1.hashCode());
		System.out.println("instance2.hashCode():"+instance2.hashCode());
		//通过单例调用doSomething()
		instance1.doSomething();
		instance2.doSomething();
	}
}

4.9.在开源框架中的应用

JDK8#java.lang.Runtime(饿汉式)
public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    private Runtime() {}
}

5.创建型模式-简单工厂模式(Gof之外)

5.1.章节内容概述

本章节涉及主要内容有:
 5.1.章节内容概述
 5.2.章节内容大纲
 5.3.简介
 5.4.应用场景
 5.5.优缺点
 5.6.角色及其职责
 5.7.模型
 5.8.示例
 5.9.在开源框架中的应用
 5.9.1.在JDK中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

5.2.章节内容大纲

5.3.简介

简单工厂模式(SimpleFactory Pattern)是一种创建型设计模式,是设计模式中最为常见的模式之一,但是不是Gof提出的23中设计模式中的一种,更像是一种编程习惯。简单工厂模式是隐藏对象的实例化过程,对外部提供一个获取对象的方法,可以根据参数获取不同类型的对象,是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

5.4.应用场景

a.客户端如果只知道传入工厂类得参数,对于如何创建对象得逻辑不关心时
b.客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应得参数
c.工厂负责创建的类少,同时系统中需要的new对象较多而且复杂时可以使用,这样一方面不会造成工厂方法中得业务逻辑太过复杂,另一方面在使用时不用一直new,直接从工厂中获取即可

5.5.优缺点

5.5.1.优点

a.屏蔽了具体的创建逻辑,客户端只需要要传入一个参数即可获取相应的结果,在一定程度上简化了对象的创建过程
b.将实例创建过程和使用过程分离开来,实现了解耦

5.5.2.缺点

a.工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响
b.违背OCP原则,一旦添加新产品就不得不修改工厂类得逻辑,这样就会造成工厂逻辑过于复杂
c.简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构

5.6.角色及其职责

Factory(工厂)
核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
Product(抽象类产品)
工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
ConcreteProduct(具体产品)
简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例,它要实现抽象产品中声明的抽象方法(有关抽象类)

5.7.模型

5.7.1.模型类图

模型类图(有Client)
模型类图(无Client)

5.7.2.模型代码

Product.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

/**
 * Product(抽象产品)
 */
public abstract class Product {
}

ConcreteProductA.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

/**
 * ConcreteProductA(具体产品A)
 */
public class ConcreteProductA extends Product {
}

ConcreteProductB.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

/**
 * ConcreteProductB(具体产品B)
 */
public class ConcreteProductB extends Product {
}

ConcreteProductC.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

/**
 * ConcreteProductC(具体产品C)
 */
public class ConcreteProductC extends Product {
}

Factory.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

/**
 * Factory(简单工厂)
 */
public class Factory {
    /**
     * 通过工厂方法生产产品
     * @param productType
     * @return
     */
    public Product factoryMethod(String productType) {
        Product product = null;
        if (productType.equals("productA")) {
            product = new ConcreteProductA();
        } else if (productType.equals("productB")) {
            product = new ConcreteProductB();
        } else if (productType.equals("productC")) {
            product = new ConcreteProductC();
        }
        return product;
    }

    /**
     * 调用工厂方法的方法
     * @param productType
     */
    public void operate(String productType){
        Product product = factoryMethod(productType);
        System.out.println(product);
    }
}

Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.model;

import org.junit.Test;

/**
 * Client(客户端)
 */
public class Client {

    @Test
    public void fun() {
        Factory factory = new Factory();
        //生产产品A
        Product productA = factory.factoryMethod("productA");
        System.out.println(productA);
        //在工厂中直接调用工厂方法
        factory.operate("productA");

        System.out.println("--------------------");
        //生产产品B
        Product productB = factory.factoryMethod("productB");
        System.out.println(productB);
        //在工厂中直接调用工厂方法
        factory.operate("productB");

        System.out.println("--------------------");
        //生产产品C
        Product productC = factory.factoryMethod("productC");
        System.out.println(productC);
        //在工厂中直接调用工厂方法
        factory.operate("productC");
    }
}

5.8.示例

5.8.1.不使用简单工厂模式

5.8.1.1.类图

类图(有Client)
类图(无Client)

5.8.1.2.代码

Pizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

import java.util.ArrayList;

public abstract class Pizza {
	protected String name;
	protected String dough;
	protected String sauce;
	protected ArrayList<String> toppings = new ArrayList<String>();
	
	public void prepare() {
		System.out.println("preparing..." + this.name);
	}
	
	public void bake() {
		System.out.println("baking..." + this.name);
	}
	
	public void cut() {
		System.out.println("cutting..." + this.name);
	}
	
	public void box() {
		System.out.println("boxing..." + this.name);
	}

	@Override
	public String toString() {
		StringBuilder pizza = new StringBuilder();
		pizza.append("------" + name + "------\n");
		pizza.append("dough:" + dough + "\n");
		pizza.append("sauce:" + sauce + "\n");
		pizza.append("toppings:\n");
		for(String topping:toppings) {
			pizza.append(topping+"\n");
		}
		return String.valueOf(pizza);
	}
	
}

CheesePizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

public class CheesePizza extends Pizza {
	public CheesePizza() {
		name = "Cheese Pizza";
		dough = "Regular Crust";
		sauce = "Marinara Pizza Sauce";
		toppings.add("Fresh Mozzarella");
		toppings.add("Parmesan");
	}
}

ClamPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

public class ClamPizza extends Pizza {
	public ClamPizza() {
		name = "Clam Pizza";
		dough = "Thin crust";
		sauce = "White garlic sauce";
		toppings.add("Clams");
		toppings.add("Grated parmesan cheese");
	}
}

PepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

public class PepperoniPizza extends Pizza {
	public PepperoniPizza() {
		name = "Pepperoni Pizza";
		dough = "Crust";
		sauce = "Marinara sauce";
		toppings.add("Sliced Pepperoni");
		toppings.add("Sliced Onion");
		toppings.add("Grated parmesan cheese");
	}
}

PizzaStore.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

public class PizzaStore {

	public Pizza orderPizza(Pizza pizza) {
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.nouse;

import org.junit.Test;

public class Client {
	
	@Test
	public void fun() {
		PizzaStore pizzaStore = new PizzaStore();
		Pizza cheesePizza = pizzaStore.orderPizza(new CheesePizza());
		System.out.println(cheesePizza);
		Pizza pepperoniPizza = pizzaStore.orderPizza(new PepperoniPizza());
		System.out.println(pepperoniPizza);
		Pizza clamPizza = pizzaStore.orderPizza(new ClamPizza());
		System.out.println(clamPizza);
	}

}

5.8.2.使用简单工厂模式

5.8.2.1.类图

类图(有Client)
类图(无Client)

5.8.2.2.代码

Pizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

import java.util.ArrayList;

public abstract class Pizza {
	protected String name;
	protected String dough;
	protected String sauce;
	protected ArrayList<String> toppings = new ArrayList<String>();
	
	public void prepare() {
		System.out.println("preparing..." + this.name);
	}
	
	public void bake() {
		System.out.println("baking..." + this.name);
	}
	
	public void cut() {
		System.out.println("cutting..." + this.name);
	}
	
	public void box() {
		System.out.println("boxing..." + this.name);
	}

	@Override
	public String toString() {
		StringBuilder pizza = new StringBuilder();
		pizza.append("------" + name + "------\n");
		pizza.append("dough:" + dough + "\n");
		pizza.append("sauce:" + sauce + "\n");
		pizza.append("toppings:\n");
		for(String topping:toppings) {
			pizza.append(topping+"\n");
		}
		return String.valueOf(pizza);
	}
	
}

CheesePizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

public class CheesePizza extends Pizza{
	public CheesePizza() {
		name = "Cheese Pizza";
		dough = "Regular Crust";
		sauce = "Marinara Pizza Sauce";
		toppings.add("Fresh Mozzarella");
		toppings.add("Parmesan");
	}
}

ClamPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

public class ClamPizza extends Pizza{
	public ClamPizza() {
		name = "Clam Pizza";
		dough = "Thin crust";
		sauce = "White garlic sauce";
		toppings.add("Clams");
		toppings.add("Grated parmesan cheese");
	}
}

PepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

public class PepperoniPizza extends Pizza{
	public PepperoniPizza() {
		name = "Pepperoni Pizza";
		dough = "Crust";
		sauce = "Marinara sauce";
		toppings.add("Sliced Pepperoni");
		toppings.add("Sliced Onion");
		toppings.add("Grated parmesan cheese");
	}
}

PizzaStoreFactory.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

public class PizzaStoreFactory {

	/**
	 * 通过工厂方法生产产品
	 * @param pizzaType
	 * @return
	 */
	public Pizza createPizza(String pizzaType) {
		Pizza pizza = null;
		if (pizzaType.equals("cheese")) {
			pizza = new CheesePizza();
		} else if (pizzaType.equals("pepperoni")) {
			pizza = new PepperoniPizza();
		} else if (pizzaType.equals("clam")) {
			pizza = new ClamPizza();
		} 
		return pizza;
	}

	/**
	 * 调用工厂方法的方法
	 * @param pizzaType
	 * @return
	 */
	public Pizza orderPizza(String pizzaType) {
		Pizza pizza = createPizza(pizzaType);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

Client.java
package com.dragonsoft.designpattern.create.factory.simplefactory.use;

import org.junit.Test;

public class Client {
	
	@Test
	public void fun() {
		PizzaStoreFactory pizzaFactory = new PizzaStoreFactory();
		Pizza cheesePizza = pizzaFactory.orderPizza("cheese");
		System.out.println(cheesePizza);
		Pizza pepperoniPizza = pizzaFactory.orderPizza("pepperoni");
		System.out.println(pepperoniPizza);
		Pizza clamPizza = pizzaFactory.orderPizza("clam");
		System.out.println(clamPizza);
	}

}

5.9.在开源框架中的应用

5.9.1.在JDK中的应用

JDK8#java.util.Calendar
说明
其中的createCalendar()方法根据传入参数的不同创建出不同的Calendar抽象类的子类,也就是根据传入参数的不同创建出了不同的对象,对调用这个方法的方法而言,屏蔽了具体的创建过程,只需要传入参数即可获取对象,符合简单工厂模式要求

类图
代码
public abstract class Calendar {
    public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }

    public static Calendar getInstance(TimeZone zone)
    {
        return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
    }

    public static Calendar getInstance(Locale aLocale)
    {
        return createCalendar(TimeZone.getDefault(), aLocale);
    }

    public static Calendar getInstance(TimeZone zone,
                                       Locale aLocale)
    {
        return createCalendar(zone, aLocale);
    }

    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }
    ...
}
可以看出,在getInstance()方法中调用了createCalendar()方法,只需要传入zone, aLocale,就可以获得一个Calendar对象

6.创建型模式-工厂模式

6.1.章节内容概述

本章节涉及主要内容有:
 6.1.章节内容概述
 6.2.章节内容大纲
 6.3.简介
 6.4.应用场景
 6.5.优缺点
 6.6.角色及其职责
 6.7.模型
 6.8.示例
 6.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

6.2.章节内容大纲

6.3.简介

工厂模式(Factory Pattern)又称工厂方法模式(FactoryMethod Pattern)是一种创建型设计模式,工厂方法模式是简单工厂模式的进一步抽象和推广,将原来在简单工厂中创建的对象改为在工厂类的子类中创建,是GoF设计模式的一种。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点,同时遵循OCP原则。在工厂方法模式中,提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

6.4.应用场景

a.客户端不关心它所要创建对象的类(产品类)的时候
b.客户端知道它所要创建对象的类(产品类),但不关心如何创建的时候

6.5.优缺点

6.5.1.优点

a.使用工厂方法用来创建客户所需要的产品,隐藏了具体产品类的实例化过程,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名
b.加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。增加了系统的可扩展性,符合OCP开闭原则
c.每个产品都对应一个工厂,所以可以在这个产品对应的工厂中更为细致的控制产品的创建过程,而不会影响到其他的产品

6.5.2.缺点

a.每增加一个新产品,都需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,这样系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
b.由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,进而增加了系统的实现难度。

6.6.角色及其职责

AbstractProduct(抽象产品)
工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
ConcreteProduct(具体产品)
工厂类所创建的实际对象
AbstractFactory(抽象工厂)
提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类)
ConcreteFactory(具体工厂)
提供实际创建对象的方法

6.7.模型

6.7.1.模型类图

模型类图(有Client)
模型类图(无Client)

6.7.2.模型代码

Product.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * Product(抽象产品)
 */
public abstract class AbstractProduct {
}

ConcreteProductA.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteProductA(具体产品A)
 */
public class ConcreteProductA extends AbstractProduct {
}

ConcreteProductB.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteProductB(具体产品B)
 */
public class ConcreteProductB extends AbstractProduct {
}

ConcreteProductC.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteProductC(具体产品C)
 */
public class ConcreteProductC extends AbstractProduct {
}

Factory.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * AbstractFactory(抽象工厂)
 */
public abstract class AbstractFactory {
    /**
     * 通过工厂方法生产产品
     * @return
     */
    public abstract AbstractProduct factoryMethod();

    /**
     * 调用工厂方法的方法
     */
    public void operate(){
        AbstractProduct product = factoryMethod();
        System.out.println(product);
    }
}

ConcreteFactoryA.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteFactoryA(生产ProductA的具体工厂)
 */
public class ConcreteFactoryA extends AbstractFactory {
    @Override
    public AbstractProduct factoryMethod() {
        return new ConcreteProductA();
    }
}

ConcreteFactoryB.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteFactoryB(生产ProductB的具体工厂)
 */
public class ConcreteFactoryB extends AbstractFactory {
    @Override
    public AbstractProduct factoryMethod() {
        return new ConcreteProductB();
    }
}

ConcreteFactoryC.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

/**
 * ConcreteFactoryC(生产ProductC的具体工厂)
 */
public class ConcreteFactoryC extends AbstractFactory {
    @Override
    public AbstractProduct factoryMethod() {
        return new ConcreteProductC();
    }
}

Client.java
package com.dragonsoft.designpattern.create.factory.factorymethod.model;

import org.junit.Test;

/**
 * 客户端
 */
public class Client {
    @Test
    public void fun() {
        //获取生产产品A的工厂
        AbstractFactory factoryA = new ConcreteFactoryA();
        //生产产品A
        AbstractProduct productA = factoryA.factoryMethod();
        System.out.println(productA);
        //在工厂A中直接调用工厂方法
        factoryA.operate();

        System.out.println("--------------------");
        //获取生产产品B的工厂
        AbstractFactory factoryB = new ConcreteFactoryB();
        //生产产品B
        AbstractProduct productB = factoryB.factoryMethod();
        System.out.println(productB);
        //在工厂B中直接调用工厂方法
        factoryB.operate();

        System.out.println("--------------------");
        //获取生产产品C的工厂
        AbstractFactory factoryC = new ConcreteFactoryC();
        //生产产品C
        AbstractProduct productC = factoryC.factoryMethod();
        System.out.println(productC);
        //在工厂C中直接调用工厂方法
        factoryC.operate();
    }
}

6.8.示例

6.8.1.不使用工厂模式(实际上使用了简单工厂模式)

6.8.1.1.类图

类图(有Client)
类图(无Client)

6.8.1.1.代码

Pizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

import java.util.ArrayList;

public abstract class Pizza {
	protected String name;
	protected String dough;
	protected String sauce;
	protected ArrayList<String> toppings = new ArrayList<String>();

	public void prepare() {
		System.out.println("Prepare " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (String topping : toppings) {
			System.out.println("   " + topping);
		}
	}

	public void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}

	public void cut() {
		System.out.println("Cut the pizza into diagonal slices");
	}

	public void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		for (String topping : toppings) {
			display.append(topping + "\n");
		}
		return display.toString();
	}
}

ChicagoStyleCheesePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class ChicagoStyleCheesePizza extends Pizza {

	public ChicagoStyleCheesePizza() { 
		name = "Chicago Style Deep Dish Cheese Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStyleClamPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class ChicagoStyleClamPizza extends Pizza {
	public ChicagoStyleClamPizza() {
		name = "Chicago Style Clam Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Frozen Clams from Chesapeake Bay");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStylePepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class ChicagoStylePepperoniPizza extends Pizza {
	public ChicagoStylePepperoniPizza() {
		name = "Chicago Style Pepperoni Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
		toppings.add("Sliced Pepperoni");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStyleVeggiePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class ChicagoStyleVeggiePizza extends Pizza {
	public ChicagoStyleVeggiePizza() {
		name = "Chicago Deep Dish Veggie Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

NYStyleCheesePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class NYStyleCheesePizza extends Pizza {

	public NYStyleCheesePizza() { 
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
	}
}


NYStyleClamPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class NYStyleClamPizza extends Pizza {
	
	public NYStyleClamPizza() {
		name = "NY Style Clam Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Fresh Clams from Long Island Sound");
	}
}

NYStylePepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class NYStylePepperoniPizza extends Pizza {

	public NYStylePepperoniPizza() {
		name = "NY Style Pepperoni Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Sliced Pepperoni");
		toppings.add("Garlic");
		toppings.add("Onion");
		toppings.add("Mushrooms");
		toppings.add("Red Pepper");
	}
}

NYStyleVeggiePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

public class NYStyleVeggiePizza extends Pizza {

	public NYStyleVeggiePizza() {
		name = "NY Style Veggie Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Garlic");
		toppings.add("Onion");
		toppings.add("Mushrooms");
		toppings.add("Red Pepper");
	}
}

PizzaStore.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

/**
 * 不使用工厂(方法)模式(实际上使用了简单工厂模式)
 */
public class PizzaStore {
	public Pizza createPizza(String pizzaStyle, String pizzaType) {
		Pizza pizza = null;
		if (pizzaStyle.equals("NY")) {
			if (pizzaType.equals("cheese")) {
				pizza = new NYStyleCheesePizza();
			} else if (pizzaType.equals("veggie")) {
				pizza = new NYStyleVeggiePizza();
			} else if (pizzaType.equals("clam")) {
				pizza = new NYStyleClamPizza();
			} else if (pizzaType.equals("pepperoni")) {
				pizza = new NYStylePepperoniPizza();
			}
		} else if (pizzaStyle.equals("Chicago")) {
			if (pizzaType.equals("cheese")) {
				pizza = new ChicagoStyleCheesePizza();
			} else if (pizzaType.equals("veggie")) {
				pizza = new ChicagoStyleVeggiePizza();
			} else if (pizzaType.equals("clam")) {
				pizza = new ChicagoStyleClamPizza();
			} else if (pizzaType.equals("pepperoni")) {
				pizza = new ChicagoStylePepperoniPizza();
			}
		} else {
			System.out.println("Error: invalid type of pizza");
			return null;
		}
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}

	/**
	 * 调用工厂方法的方法
	 * @param pizzaType
	 * @return
	 */
	public Pizza orderPizza(String pizzaStyle, String pizzaType) {
		Pizza pizza = createPizza(pizzaStyle,pizzaType);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

Client.java
package com.dragonsoft.designpattern.create.factory.factorymethod.nouse;

import org.junit.Test;

public class Client {
	@Test
	public void fun() {
		//测试DependentPizzaFactory
		PizzaStore pizzaStore = new PizzaStore();
		Pizza pizza = pizzaStore.orderPizza("NY", "cheese");
		System.out.println("Lee ordered a " + pizza.getName() + "\n");
	}
}

6.8.2.使用工厂模式

6.8.2.1.类图

类图(有Client)
类图(无Client)

6.8.2.2.代码

Pizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

import java.util.ArrayList;

public abstract class Pizza {
	protected String name;
	protected String dough;
	protected String sauce;
	protected ArrayList<String> toppings = new ArrayList<String>();

	public void prepare() {
		System.out.println("Prepare " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (String topping : toppings) {
			System.out.println("   " + topping);
		}
	}

	public void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}

	public void cut() {
		System.out.println("Cut the pizza into diagonal slices");
	}

	public void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		for (String topping : toppings) {
			display.append(topping + "\n");
		}
		return display.toString();
	}
}

ChicagoStyleCheesePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class ChicagoStyleCheesePizza extends Pizza {

	public ChicagoStyleCheesePizza() { 
		name = "Chicago Style Deep Dish Cheese Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStyleClamPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class ChicagoStyleClamPizza extends Pizza {
	public ChicagoStyleClamPizza() {
		name = "Chicago Style Clam Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Frozen Clams from Chesapeake Bay");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStylePepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class ChicagoStylePepperoniPizza extends Pizza {
	public ChicagoStylePepperoniPizza() {
		name = "Chicago Style Pepperoni Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
		toppings.add("Sliced Pepperoni");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

ChicagoStyleVeggiePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class ChicagoStyleVeggiePizza extends Pizza {
	public ChicagoStyleVeggiePizza() {
		name = "Chicago Deep Dish Veggie Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
	}
 
	@Override
	public void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}

NYStyleCheesePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class NYStyleCheesePizza extends Pizza {

	public NYStyleCheesePizza() { 
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
	}
}


NYStyleClamPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class NYStyleClamPizza extends Pizza{
	
	public NYStyleClamPizza() {
		name = "NY Style Clam Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Fresh Clams from Long Island Sound");
	}
}

NYStylePepperoniPizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class NYStylePepperoniPizza extends Pizza {

	public NYStylePepperoniPizza() {
		name = "NY Style Pepperoni Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Sliced Pepperoni");
		toppings.add("Garlic");
		toppings.add("Onion");
		toppings.add("Mushrooms");
		toppings.add("Red Pepper");
	}
}

NYStyleVeggiePizza.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class NYStyleVeggiePizza extends Pizza {

	public NYStyleVeggiePizza() {
		name = "NY Style Veggie Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
 
		toppings.add("Grated Reggiano Cheese");
		toppings.add("Garlic");
		toppings.add("Onion");
		toppings.add("Mushrooms");
		toppings.add("Red Pepper");
	}
}

PizzaFactory.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public abstract class PizzaStoreFactory {
	
	/**
	 * 工厂方法
	 * @param pizzaType
	 * @return
	 */
	public abstract Pizza createPizza(String pizzaType);

	/**
	 * 调用工厂方法的方法
	 * @param pizzaType
	 * @return
	 */
	public Pizza orderPizza(String pizzaType) {
		Pizza pizza = createPizza(pizzaType);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

NYPizzaFactory.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class NYPizzaStoreFactory extends PizzaStoreFactory {

	@Override
	public Pizza createPizza(String pizzaType) {
		if (pizzaType.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (pizzaType.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (pizzaType.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (pizzaType.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else {
			return null;
		}
	}
}

ChicagoPizzaStoreFactory.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

public class ChicagoPizzaStoreFactory extends PizzaStoreFactory {

	@Override
	public Pizza createPizza(String pizzaType) {
    	if (pizzaType.equals("cheese")) {
        		return new ChicagoStyleCheesePizza();
    	} else if (pizzaType.equals("veggie")) {
    	    	return new ChicagoStyleVeggiePizza();
    	} else if (pizzaType.equals("clam")) {
    	    	return new ChicagoStyleClamPizza();
    	} else if (pizzaType.equals("pepperoni")) {
        		return new ChicagoStylePepperoniPizza();
    	} else {
			return null;
		}
	}
}

Client.java
package com.dragonsoft.designpattern.create.factory.factorymethod.use;

import org.junit.Test;

public class Client {
	@Test
	public void fun() {
		PizzaStoreFactory nyPizzaStoreFactory = new NYPizzaStoreFactory();
		PizzaStoreFactory chicagoPizzaStoreFactory = new ChicagoPizzaStoreFactory();
 
		Pizza pizza = nyPizzaStoreFactory.orderPizza("cheese");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoPizzaStoreFactory.orderPizza("cheese");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");

		pizza = nyPizzaStoreFactory.orderPizza("clam");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoPizzaStoreFactory.orderPizza("clam");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");

		pizza = nyPizzaStoreFactory.orderPizza("pepperoni");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoPizzaStoreFactory.orderPizza("pepperoni");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");

		pizza = nyPizzaStoreFactory.orderPizza("veggie");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
 
		pizza = chicagoPizzaStoreFactory.orderPizza("veggie");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");
	}
}

6.9.在开源框架中的应用

6.9.1.在JDK中的应用

JDK8#集合框架部分代码
说明
Collection是抽象工厂,Collection中iterator()方法就是工厂方法,ArrayList和HashSet就是具体工厂,Iterator是抽象产品,具体产品是ArrayList和HasHSet中iterator()方法的return new Itr()创建出来的对象

类图
代码
    Iterable.java
public interface Iterable<T> {
    Iterator<T> iterator();
}
    Collection.java
public interface Collection<E> extends Iterable<E> {
    Iterator<E> iterator();
}
    AbstractCollection.java
public abstract class AbstractCollection<E> implements Collection<E> {
    public abstract Iterator<E> iterator();
}
    AbstractList.java
public abstract class AbstractList<E> extends AbstractCollection<E> {
    public Iterator<E> iterator() {
        return new Itr();
    }
}
    ArrayList.java
public class ArrayList<E> extends AbstractList<E> {
    public Iterator<E> iterator() {
        return new Itr();
    }
}
    AbstractSet.java
public abstract class AbstractSet<E> extends AbstractCollection<E> {
    public abstract Iterator<E> iterator();
}
    HashSet.java
public class HashSet<E> extends AbstractSet<E> implements Set<E> {
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }
}

7.创建型模式-抽象工厂模式

7.1.章节内容概述

本章节涉及主要内容有:
 7.1.章节内容概述
 7.2.章节内容大纲
 7.3.简介
 7.4.应用场景
 7.5.优缺点
 7.6.角色及其职责
 7.7.模型
 7.8.示例
 7.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

7.2.章节内容大纲

7.3.简介

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,是工厂方法模式的升级版本,解决了简单工厂模式中工厂类职责太重的问题,抽象工厂中提供一个创建一系列相关或相互依赖对象的接口,这个接口中定义了创建多个不同的对象方法,但是让该接口的子类去实例化具体的类,把实例化具体对象的过程延迟到了子类中去实现。与工厂方法模式不同的是,抽象工厂模式中的具体工厂不再是只能创建一种产品,一个具体的工厂可以创建一个产品族的产品。

7.4.应用场景

a.客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
b.强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
c.提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现

7.5.优缺点

7.5.1.优点

a.具体产品在应用层的代码隔离,无需关心创建的细节
b.将一个系列的产品统一到一起创建

7.5.2.缺点

a.具体产品在应用层的代码隔离,无需关系创建的细节
b.将一个系列的产品统一到一起创建

7.6.角色及其职责

AbstractFactory
提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
ConcreteFactory
主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
AbstractProduct
定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
ConcreteProduct
实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

7.7.模型

7.7.1.模型类图

模型类图(有Client)
模型类图(无Client)

7.7.2.模型代码

ProductPart1.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part1部分接口
 */
public interface ProductPart1 {
}

ProductPart1LevelA.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part1部分 A级别
 */
public class ProductPart1LevelA implements ProductPart1{
    @Override
    public String toString() {
        return "ProductPart1-LevelA";
    }
}

ProductPart1LevelB.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part1部分 B级别
 */
public class ProductPart1LevelB implements ProductPart1{
    @Override
    public String toString() {
        return "ProductPart1-LevelB";
    }
}

ProductPart1LevelC.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part1部分 C级别
 */
public class ProductPart1LevelC implements ProductPart1{
    @Override
    public String toString() {
        return "ProductPart1-LevelC";
    }
}

ProductPart2.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part2部分接口
 */
public interface ProductPart2 {
}

ProductPart2LevelA.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part2部分 A级别
 */
public class ProductPart2LevelA implements ProductPart2{
    @Override
    public String toString() {
        return "ProductPart2-LevelA";
    }
}

ProductPart2LevelB.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part2部分 B级别
 */
public class ProductPart2LevelB implements ProductPart2{
    @Override
    public String toString() {
        return "ProductPart2-LevelB";
    }
}

ProductPart2LevelC.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part2部分 C级别
 */
public class ProductPart2LevelC implements ProductPart2{
    @Override
    public String toString() {
        return "ProductPart2-LevelC";
    }
}

ProductPart3.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part3部分接口
 */
public interface ProductPart3 {
}

ProductPart3LevelA.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part3部分 A级别
 */
public class ProductPart3LevelA implements ProductPart3{
    @Override
    public String toString() {
        return "ProductPart3-LevelA";
    }
}

ProductPart3LevelB.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part3部分 B级别
 */
public class ProductPart3LevelB implements ProductPart3{
    @Override
    public String toString() {
        return "ProductPart3-LevelB";
    }
}

ProductPart3LevelC.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * 产品的Part3部分 C级别
 */
public class ProductPart3LevelC implements ProductPart3{
    @Override
    public String toString() {
        return "ProductPart3-LevelC";
    }
}

AbstractFactory.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * AbstractFactory(抽象工厂:用于创建一个产品族的产品)
 * ProductPart1,ProductPart2,ProductPart3是一个产品族中的不同产品,可以理解为如下情况
 * a.汽车案例
 *  Product                     : 汽车
 *  产品族: 轮胎、座椅、方向盘
 *  ProductPart1                : 轮胎
 *      ProductPart1LevelA      : 特斯拉轮胎
 *      ProductPart1LevelB      : 丰田轮胎
 *      ProductPart1LevelC      : 五菱轮胎
 *  ProductPart2                : 座椅
 *      ProductPart2LevelA      : 特斯拉座椅
 *      ProductPart2LevelB      : 丰田座椅
 *      ProductPart2LevelC      : 五菱座椅
 *  ProductPart3                : 方向盘
 *      ProductPart3LevelA      : 特斯拉方向盘
 *      ProductPart3LevelB      : 丰田方向盘
 *      ProductPart3LevelC      : 五菱方向盘
 * b.运动服装案例
 *  Product                     : 一整套运动服装
 *  产品族: 上衣、裤子、鞋子
 *  ProductPart1                : 上衣
 *      ProductPart1LevelA      : 耐克上衣
 *      ProductPart1LevelB      : 安踏上衣
 *      ProductPart1LevelC      : 特价上衣
 *  ProductPart2                : 裤子
 *      ProductPart2LevelA      : 耐克裤子
 *      ProductPart2LevelB      : 安踏裤子
 *      ProductPart2LevelC      : 特价裤子
 *  ProductPart3                : 鞋子
 *      ProductPart3LevelA      : 耐克鞋子
 *      ProductPart3LevelB      : 耐克鞋子
 *      ProductPart3LevelC      : 耐克鞋子
 * c.工厂案例
 *  Product                     : 工厂
 *  产品族: 汽车、自行车、摩托车
 *  ProductPart1                : 汽车
 *      ProductPart1LevelA      : 特斯拉汽车
 *      ProductPart1LevelB      : 长安汽车
 *      ProductPart1LevelC      : 奇瑞汽车
 *  ProductPart2                : 自行车
 *      ProductPart2LevelA      : 特斯自行车
 *      ProductPart2LevelB      : 长安自行车
 *      ProductPart2LevelC      : 奇瑞自行车
 *  ProductPart3                : 摩托车
 *      ProductPart3LevelA      : 特斯摩托车
 *      ProductPart3LevelB      : 长安摩托车
 *      ProductPart3LevelC      : 奇瑞摩托车
 */
public abstract class AbstractFactory {
    /**
     * 通过工厂方法生产产品的Part1部分
     * @return
     */
    public abstract ProductPart1 factoryMethod4ProductPart1();
    /**
     * 通过工厂方法生产产品的Part2部分
     * @return
     */
    public abstract ProductPart2 factoryMethod4ProductPart2();
    /**
     * 通过工厂方法生产产品的Part3部分
     * @return
     */
    public abstract ProductPart3 factoryMethod4ProductPart3();

}

ConcreteFactoryLevelA.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * ConcreteFactoryLevelA(生产A级别Product的工厂)
 */
public class ConcreteFactoryLevelA extends AbstractFactory {

    @Override
    public ProductPart1 factoryMethod4ProductPart1() {
        return new ProductPart1LevelA();
    }

    @Override
    public ProductPart2 factoryMethod4ProductPart2() {
        return new ProductPart2LevelA();
    }

    @Override
    public ProductPart3 factoryMethod4ProductPart3() {
        return new ProductPart3LevelA();
    }
}

ConcreteFactoryLevelB.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * ConcreteFactoryLevelB(生产B级别Product的工厂)
 */
public class ConcreteFactoryLevelB extends AbstractFactory {
    @Override
    public ProductPart1 factoryMethod4ProductPart1() {
        return new ProductPart1LevelB();
    }

    @Override
    public ProductPart2 factoryMethod4ProductPart2() {
        return new ProductPart2LevelB();
    }

    @Override
    public ProductPart3 factoryMethod4ProductPart3() {
        return new ProductPart3LevelB();
    }
}

ConcreteFactoryLevelC.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

/**
 * ConcreteFactoryLevelC(生产C级别Product的工厂)
 */
public class ConcreteFactoryLevelC extends AbstractFactory {
    @Override
    public ProductPart1 factoryMethod4ProductPart1() {
        return new ProductPart1LevelC();
    }

    @Override
    public ProductPart2 factoryMethod4ProductPart2() {
        return new ProductPart2LevelC();
    }

    @Override
    public ProductPart3 factoryMethod4ProductPart3() {
        return new ProductPart3LevelC();
    }
}

Client.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.model;

import org.junit.Test;

/**
 * 客户端
 */
public class Client {
    @Test
    public void fun() {
        AbstractFactory concreteFactoryLevelA = new ConcreteFactoryLevelA();
        ProductPart1 productPart1LevelA = concreteFactoryLevelA.factoryMethod4ProductPart1();
        ProductPart2 productPart2LevelA = concreteFactoryLevelA.factoryMethod4ProductPart2();
        ProductPart3 productPart3LevelA = concreteFactoryLevelA.factoryMethod4ProductPart3();
        System.out.println("productLevelA: " + productPart1LevelA +"," + productPart2LevelA + "," + productPart3LevelA);

        System.out.println("--------------------");
        AbstractFactory concreteFactoryLevelB = new ConcreteFactoryLevelB();
        ProductPart1 productPart1LevelB = concreteFactoryLevelB.factoryMethod4ProductPart1();
        ProductPart2 productPart2LevelB = concreteFactoryLevelB.factoryMethod4ProductPart2();
        ProductPart3 productPart3LevelB = concreteFactoryLevelB.factoryMethod4ProductPart3();
        System.out.println("productLevelB: " + productPart1LevelB +"," + productPart2LevelB + "," + productPart3LevelB);

        System.out.println("--------------------");
        AbstractFactory concreteFactoryLevelC = new ConcreteFactoryLevelC();
        ProductPart1 productPart1LevelC = concreteFactoryLevelC.factoryMethod4ProductPart1();
        ProductPart2 productPart2LevelC = concreteFactoryLevelC.factoryMethod4ProductPart2();
        ProductPart3 productPart3LevelC = concreteFactoryLevelC.factoryMethod4ProductPart3();
        System.out.println("productLevelC: " + productPart1LevelC +"," + productPart2LevelC + "," + productPart3LevelC);
    }
}

7.8.示例

7.8.1.不使用抽象工厂模式

7.8.2.使用抽象工厂模式

类图(有Client)
类图(无Client)
代码
AbstractClothesProduceFactory.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

/**
 * 服装工厂
 * @author lingwh
 *
 */
public abstract class AbstractClothesProduceFactory {
	
	//生产帽子
	public abstract AbstractHat produceHat();
	//生产夹克衫
	public abstract AbstractJacket produceJacket();
	//生产裤子
	public abstract AbstractTrousers produceTrousers();
	//生产鞋子
	public abstract AbstractShoes produceShoes();
}

AdidasClothesProduceFactory.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class AdidasClothesProduceFactory extends AbstractClothesProduceFactory {

	@Override
	public AbstractHat produceHat() {
		return new AdidasHat();
	}

	@Override
	public AbstractJacket produceJacket() {
		return new AdidasJacket();
	}

	@Override
	public AbstractTrousers produceTrousers() {
		return new AdidasTrousers();
	}

	@Override
	public AbstractShoes produceShoes() {
		return new AdidasShoes();
	}

}

NikeClothesProduceFactory.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class NikeClothesProduceFactory extends AbstractClothesProduceFactory {

	@Override
	public AbstractHat produceHat() {
		return new NikeHat();
	}

	@Override
	public AbstractJacket produceJacket() {
		return new NikeJacket();
	}

	@Override
	public AbstractTrousers produceTrousers() {
		return new NikeTrousers();
	}

	@Override
	public AbstractShoes produceShoes() {
		return new NikeShoes();
	}

}

PumaClothesProduceFactory.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class PumaClothesProduceFactory extends AbstractClothesProduceFactory {

	@Override
	public AbstractHat produceHat() {
		return new PumaHat();
	}

	@Override
	public AbstractJacket produceJacket() {
		return new PumaJacket();
	}

	@Override
	public AbstractTrousers produceTrousers() {
		return new PumaTrousers();
	}

	@Override
	public AbstractShoes produceShoes() {
		return new PumaShoes();
	}

}

AbstractHat.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public abstract class AbstractHat {
	public abstract void produce();
}

AdidasHat.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class AdidasHat extends AbstractHat {

	@Override
	public void produce() {
		System.out.println("Adidas Hat produce ok...");
	}

}

NikeHat.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class NikeHat extends AbstractHat {

	@Override
	public void produce() {
		System.out.println("Nike Hat produce ok...");
	}

}

PumaHat.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class PumaHat extends AbstractHat {

	@Override
	public void produce() {
		System.out.println("Puma Hat produce ok...");
	}

}

AbstractJacket.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public abstract class AbstractJacket {
	public abstract void produce();
}

AdidasJacket.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class AdidasJacket extends AbstractJacket {

	@Override
	public void produce() {
		System.out.println("Adidas Jacket produce ok...");
	}

}

NikeJacket.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class NikeJacket extends AbstractJacket {

	@Override
	public void produce() {
		System.out.println("Nike Jacket produce ok...");
	}

}

PumaJacket.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class PumaJacket extends AbstractJacket {

	@Override
	public void produce() {
		System.out.println("Puma Jacket produce ok...");
	}

}

AbstractShoes.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public abstract class AbstractShoes {
	public abstract void produce();
}

AdidasShoes.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class AdidasShoes extends AbstractShoes {

	@Override
	public void produce() {
		System.out.println("Adidas Shoes produce ok...");
	}

}

NikeShoes.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class NikeShoes extends AbstractShoes {

	@Override
	public void produce() {
		System.out.println("Nike Shoes produce ok...");
	}

}

PumaShoes.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class PumaShoes extends AbstractShoes {

	@Override
	public void produce() {
		System.out.println("Puma Shoes produce ok...");
	}

}

AbstractTrousers.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public abstract class AbstractTrousers {
	public abstract void produce();
}

AdidasTrousers.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class AdidasTrousers extends AbstractTrousers {

	@Override
	public void produce() {
		System.out.println("Adidas Trousers produce ok...");
	}

}

NikeTrousers.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class NikeTrousers extends AbstractTrousers {

	@Override
	public void produce() {
		System.out.println("Nike Trousers produce ok...");
	}

}

PumaTrousers.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

public class PumaTrousers extends AbstractTrousers {

	@Override
	public void produce() {
		System.out.println("Puma Trousers produce ok...");
	}

}

Client.java
package com.dragonsoft.designpattern.create.factory.abstractfactory.use;

import org.junit.Test;

public class Client {
	
	@Test
	public void fun() {
		//Adidas工厂
		AbstractClothesProduceFactory adidasClothesFactory = new AdidasClothesProduceFactory();
		AbstractHat adidasHat = adidasClothesFactory.produceHat();
		AbstractJacket adidasJacket = adidasClothesFactory.produceJacket();
		AbstractTrousers adidasTrousers = adidasClothesFactory.produceTrousers();
		AbstractShoes adidasShoes = adidasClothesFactory.produceShoes();
		adidasHat.produce();
		adidasJacket.produce();
		adidasTrousers.produce();
		adidasShoes.produce();
		
		System.out.println("-------------------------------");
		//Nike工厂
		AbstractClothesProduceFactory nikeClothesFactory = new NikeClothesProduceFactory();
		AbstractHat nikeHat = nikeClothesFactory.produceHat();
		AbstractJacket nikeJacket = nikeClothesFactory.produceJacket();
		AbstractTrousers nikeTrousers = nikeClothesFactory.produceTrousers();
		AbstractShoes nikeShoes = nikeClothesFactory.produceShoes();
		nikeHat.produce();
		nikeJacket.produce();
		nikeTrousers.produce();
		nikeShoes.produce();
		
		System.out.println("-------------------------------");
		//Puma工厂
		AbstractClothesProduceFactory pumaClothesFactory = new PumaClothesProduceFactory();
		AbstractHat pumaHat = pumaClothesFactory.produceHat();
		AbstractJacket pumaJacket = pumaClothesFactory.produceJacket();
		AbstractTrousers pumaTrousers = pumaClothesFactory.produceTrousers();
		AbstractShoes pumaShoes = pumaClothesFactory.produceShoes();
		pumaHat.produce();
		pumaJacket.produce();
		pumaTrousers.produce();
		pumaShoes.produce();
	}
}

7.9.在开源框架中的应用

8.创建型模式-原型模式

8.1.章节内容概述

本章节涉及主要内容有:
 8.1.章节内容概述
 8.2.章节内容大纲
 8.3.简介
 8.4.应用场景
 8.5.优缺点
 8.6.角色及其职责
 8.7.模型
 8.8.示例
 8.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

8.2.章节内容大纲

8.3.简介

8.4.应用场景

8.5.优缺点

8.5.1.优点

8.5.2.缺点

8.6.角色及其职责

8.7.模型

8.7.1.模型类图

8.7.2.模型代码

8.8.示例

8.9.在开源框架中的应用

9.创建型模式-建造者模式

9.1.章节内容概述

本章节涉及主要内容有:
 9.1.章节内容概述
 9.2.章节内容大纲
 9.3.简介
 9.4.应用场景
 9.5.优缺点
 9.6.角色及其职责
 9.7.模型
 9.8.示例
 9.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

9.2.章节内容大纲

9.3.简介

9.4.应用场景

9.5.优缺点

9.5.1.优点

9.5.2.缺点

9.6.角色及其职责

9.7.模型

9.7.1.模型类图

9.7.2.模型代码

9.8.示例

9.9.在开源框架中的应用

10.结构型模式-适配器模式

10.1.章节内容概述

本章节涉及主要内容有:
 10.1.章节内容概述
 10.2.章节内容大纲
 10.3.简介
 10.4.应用场景
 10.5.优缺点
 10.6.角色及其职责
 10.7.模型
 10.8.示例
 10.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

10.2.章节内容大纲

10.3.简介

10.4.应用场景

10.5.优缺点

10.5.1.优点

10.5.2.缺点

10.6.角色及其职责

10.7.模型

10.7.1.模型类图

10.7.2.模型代码

10.8.示例

10.9.在开源框架中的应用

11.结构型模式-桥接模式

11.1.章节内容概述

本章节涉及主要内容有:
 11.1.章节内容概述
 11.2.章节内容大纲
 11.3.简介
 11.4.应用场景
 11.5.优缺点
 11.6.角色及其职责
 11.7.模型
 11.8.示例
 11.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

11.2.章节内容大纲

11.3.简介

11.4.应用场景

11.5.优缺点

11.5.1.优点

11.5.2.缺点

11.6.角色及其职责

11.7.模型

11.7.1.模型类图

11.7.2.模型代码

11.8.示例

11.9.在开源框架中的应用

12.结构型模式-装饰者模式

12.1.章节内容概述

本章节涉及主要内容有:
 12.1.章节内容概述
 12.2.章节内容大纲
 12.3.简介
 12.4.应用场景
 12.5.优缺点
 12.6.角色及其职责
 12.7.模型
 12.8.示例
 12.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

12.2.章节内容大纲

12.3.简介

12.4.应用场景

12.5.优缺点

12.5.1.优点

12.5.2.缺点

12.6.角色及其职责

12.7.模型

12.7.1.模型类图

12.7.2.模型代码

12.8.示例

12.9.在开源框架中的应用

13.结构型模式-组合模式

13.1.章节内容概述

本章节涉及主要内容有:
 13.1.章节内容概述
 13.2.章节内容大纲
 13.3.简介
 13.4.应用场景
 13.5.优缺点
 13.6.角色及其职责
 13.7.模型
 13.8.示例
 13.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

13.2.章节内容大纲

13.3.简介

13.4.应用场景

13.5.优缺点

13.5.1.优点

13.5.2.缺点

13.6.角色及其职责

13.7.模型

13.7.1.模型类图

13.7.2.模型代码

13.8.示例

13.9.在开源框架中的应用

14.结构型模式-外观模式

14.1.章节内容概述

本章节涉及主要内容有:
 14.1.章节内容概述
 14.2.章节内容大纲
 14.3.简介
 14.4.应用场景
 14.5.优缺点
 14.6.角色及其职责
 14.7.模型
 14.8.示例
 14.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

14.2.章节内容大纲

14.3.简介

14.4.应用场景

14.5.优缺点

14.5.1.优点

14.5.2.缺点

14.6.角色及其职责

14.7.模型

14.7.1.模型类图

14.7.2.模型代码

14.8.示例

14.9.在开源框架中的应用

15.结构型模式-享元模式

15.1.章节内容概述

本章节涉及主要内容有:
 15.1.章节内容概述
 15.2.章节内容大纲
 15.3.简介
 15.4.应用场景
 15.5.优缺点
 15.6.角色及其职责
 15.7.模型
 15.8.示例
 15.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

15.2.章节内容大纲

15.3.简介

15.4.应用场景

15.5.优缺点

15.5.1.优点

15.5.2.缺点

15.6.角色及其职责

15.7.模型

15.7.1.模型类图

15.7.2.模型代码

15.8.示例

15.9.在开源框架中的应用

16.结构型模式-代理模式

16.1.章节内容概述

本章节涉及主要内容有:
 16.1.章节内容概述
 16.2.章节内容大纲
 16.3.简介
 16.4.应用场景
 16.5.优缺点
 16.6.角色及其职责
 16.7.模型
 16.8.示例
 16.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

16.2.章节内容大纲

16.3.简介

16.4.应用场景

16.5.优缺点

16.5.1.优点

16.5.2.缺点

16.6.角色及其职责

16.7.模型

16.7.1.模型类图

16.7.2.模型代码

16.8.示例

16.9.在开源框架中的应用

17.行为型模式-模版方法模式

17.1.章节内容概述

本章节涉及主要内容有:
 17.1.章节内容概述
 17.2.章节内容大纲
 17.3.简介
 17.4.应用场景
 17.5.优缺点
 17.6.角色及其职责
 17.7.模型
 17.8.示例
 17.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

17.2.章节内容大纲

17.3.简介

17.4.应用场景

17.5.优缺点

17.5.1.优点

17.5.2.缺点

17.6.角色及其职责

17.7.模型

17.7.1.模型类图

17.7.2.模型代码

17.8.示例

17.9.在开源框架中的应用

18.行为型模式-命令模式

18.1.章节内容概述

本章节涉及主要内容有:
 18.1.章节内容概述
 18.2.章节内容大纲
 18.3.简介
 18.4.应用场景
 18.5.优缺点
 18.6.角色及其职责
 18.7.模型
 18.8.示例
 18.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

18.2.章节内容大纲

18.3.简介

18.4.应用场景

18.5.优缺点

18.5.1.优点

18.5.2.缺点

18.6.角色及其职责

18.7.模型

18.7.1.模型类图

18.7.2.模型代码

18.8.示例

18.9.在开源框架中的应用

19.行为型模式-迭代器模式

19.1.章节内容概述

本章节涉及主要内容有:
 19.1.章节内容概述
 19.2.章节内容大纲
 19.3.简介
 19.4.应用场景
 19.5.优缺点
 19.6.角色及其职责
 19.7.模型
 19.8.示例
 19.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

19.2.章节内容大纲

19.3.简介

19.4.应用场景

19.5.优缺点

19.5.1.优点

19.5.2.缺点

19.6.角色及其职责

19.7.模型

19.7.1.模型类图

19.7.2.模型代码

19.8.示例

19.9.在开源框架中的应用

20.行为型模式-观察者模式

20.1.章节内容概述

本章节涉及主要内容有:
 20.1.章节内容概述
 20.2.章节内容大纲
 20.3.简介
 20.4.应用场景
 20.5.优缺点
 20.6.角色及其职责
 20.7.模型
 20.8.示例
 20.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

20.2.章节内容大纲

20.3.简介

20.4.应用场景

20.5.优缺点

20.5.1.优点

20.5.2.缺点

20.6.角色及其职责

20.7.模型

20.7.1.模型类图

20.7.2.模型代码

20.8.示例

20.9.在开源框架中的应用

21.行为型模式-中介者模式

21.1.章节内容概述

本章节涉及主要内容有:
 21.1.章节内容概述
 21.2.章节内容大纲
 21.3.简介
 21.4.应用场景
 21.5.优缺点
 21.6.角色及其职责
 21.7.模型
 21.8.示例
 21.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

21.2.章节内容大纲

21.3.简介

21.4.应用场景

21.5.优缺点

21.5.1.优点

21.5.2.缺点

21.6.角色及其职责

21.7.模型

21.7.1.模型类图

21.7.2.模型代码

21.8.示例

21.9.在开源框架中的应用

22.行为型模式-备忘录模式

22.1.章节内容概述

本章节涉及主要内容有:
 22.1.章节内容概述
 22.2.章节内容大纲
 22.3.简介
 22.4.应用场景
 22.5.优缺点
 22.6.角色及其职责
 22.7.模型
 22.8.示例
 22.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

22.2.章节内容大纲

22.3.简介

22.4.应用场景

22.5.优缺点

22.5.1.优点

22.5.2.缺点

22.6.角色及其职责

22.7.模型

22.7.1.模型类图

22.7.2.模型代码

22.8.示例

22.9.在开源框架中的应用

23.行为型模式-解释器模式

23.1.章节内容概述

本章节涉及主要内容有:
 23.1.章节内容概述
 23.2.章节内容大纲
 23.3.简介
 23.4.应用场景
 23.5.优缺点
 23.6.角色及其职责
 23.7.模型
 23.8.示例
 23.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

23.2.章节内容大纲

23.3.简介

23.4.应用场景

23.5.优缺点

23.5.1.优点

23.5.2.缺点

23.6.角色及其职责

23.7.模型

23.7.1.模型类图

23.7.2.模型代码

23.8.示例

23.9.在开源框架中的应用

24.行为型模式-状态模式

24.1.章节内容概述

本章节涉及主要内容有:
 24.1.章节内容概述
 24.2.章节内容大纲
 24.3.简介
 24.4.应用场景
 24.5.优缺点
 24.6.角色及其职责
 24.7.模型
 24.8.示例
 24.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

24.2.章节内容大纲

24.3.简介

24.4.应用场景

24.5.优缺点

24.5.1.优点

24.5.2.缺点

24.6.角色及其职责

24.7.模型

24.7.1.模型类图

24.7.2.模型代码

24.8.示例

24.9.在开源框架中的应用

25.行为型模式-策略模式

25.1.章节内容概述

本章节涉及主要内容有:
 25.1.章节内容概述
 25.2.章节内容大纲
 25.3.简介
 25.4.应用场景
 25.5.优缺点
 25.6.角色及其职责
 25.7.模型
 25.8.示例
 25.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

25.2.章节内容大纲

25.3.简介

25.4.应用场景

25.5.优缺点

25.5.1.优点

25.5.2.缺点

25.6.角色及其职责

25.7.模型

25.7.1.模型类图

25.7.2.模型代码

25.8.示例

25.9.在开源框架中的应用

26.行为型模式-职责链模式

26.1.章节内容概述

本章节涉及主要内容有:
 26.1.章节内容概述
 26.2.章节内容大纲
 26.3.简介
 26.4.应用场景
 26.5.优缺点
 26.6.角色及其职责
 26.7.模型
 26.8.示例
 26.9.在开源框架中的应用
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

26.2.章节内容大纲

26.3.简介

26.4.应用场景

26.5.优缺点

26.5.1.优点

26.5.2.缺点

26.6.角色及其职责

26.7.模型

26.7.1.模型类图

26.7.2.模型代码

26.8.示例

26.9.在开源框架中的应用

27.行为型模式-访问者模式

27.1.章节内容概述

本章节涉及主要内容有:
 27.1.章节内容概述
 27.2.章节内容大纲
 27.3.简介
 27.4.应用场景
 27.5.优缺点
 27.6.角色及其职责
 27.7.模型
 27.8.示例
 27.9.在开源框架中的应用 
具体每个小节中包含的内容可使通过下面的章节内容大纲进行查看。

27.2.章节内容大纲

27.3.简介

27.4.应用场景

27.5.优缺点

27.5.1.优点

27.5.2.缺点

27.6.角色及其职责

27.7.模型

27.7.1.模型类图

27.7.2.模型代码

27.8.示例

27.9.在开源框架中的应用

上次编辑于: 2022/9/10 08:56:45
贡献者: lingwh
评论