Java设计模式

本文详细介绍了Java中的设计模式,包括7大设计原则和23种设计模式中的单例模式(懒汉式、饿汉式、静态内部类、枚举实现)和工厂方法模式(简单工厂、工厂方法、抽象工厂)。文章通过示例代码展示了各种模式的实现和优缺点,强调了它们在实际开发中的应用和重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7大设计原则

  • 单一职责原则

  • 里氏替换原则

  • 依赖倒置原则
  • 开闭原则
  • 迪米特法则(最少知道原则)
  • 接口隔离原则
  • 组合优于继承原则

23种设计模式

单例模式

懒汉式

class LazySingleton{
    private static LazySingleton instance;
    private LazySingleton(){}

    public static LazySingleton getInstance()  {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

public static void main(String[] args) {
        LazySingleton instance = LazySingleton.getInstance();
        LazySingleton instance1 = LazySingleton.getInstance();
        System.out.println(instance1 == instance);//true
    }

多线程情况下:

class LazySingleton{
    private static LazySingleton instance;
    private LazySingleton(){}

    public static LazySingleton getInstance()  {
        if (instance == null) {
            try {
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }

            instance = new LazySingleton();
        }
        return instance;
    }
}

public class LazySingletonTest {
    public static void main(String[] args) {
        new Thread(()->{
            LazySingleton instance3 = LazySingleton.getInstance();
            System.out.println(instance3);
        }).start();

        new Thread(() ->{
            LazySingleton instance4 = LazySingleton.getInstance();
            System.out.println(instance4);
        }).start();
    }
}

结果:
com.junrui.designpattern.singleton.LazySingleton@90472a2
com.junrui.designpattern.singleton.LazySingleton@1e057600

给方法加上锁之后

 public static synchronized LazySingleton getInstance(){
        if (instance == null) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            instance = new LazySingleton();
        }
        return instance;
    }

new Thread(()->{
            LazySingleton instance3 = LazySingleton.getInstance();
            System.out.println(instance3);
        }).start();

        new Thread(() ->{
            LazySingleton instance4 = LazySingleton.getInstance();
            System.out.println(instance4);
        }).start();

结果:
com.junrui.designpattern.singleton.LazySingleton@19281561
com.junrui.designpattern.singleton.LazySingleton@19281561

给方法上面添加锁,锁的力度大性能差,然后在创建实例的时候,加锁

  public static  LazySingleton getInstance(){
        if (instance == null) {
            synchronized (LazySingleton.class){
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                instance = new LazySingleton();
            }
        }
        return instance;
    }

 new Thread(()->{
            LazySingleton instance3 = LazySingleton.getInstance();
            System.out.println(instance3);
        }).start();

        new Thread(() ->{
            LazySingleton instance4 = LazySingleton.getInstance();
            System.out.println(instance4);
        }).start();

结果:
com.junrui.designpattern.singleton.LazySingleton@4388eabf
com.junrui.designpattern.singleton.LazySingleton@626213bf

在给创建对象时加锁的同时,判断对象是否为空,双重判断

public static  LazySingleton getInstance(){
        if (instance == null) {
            synchronized (LazySingleton.class){
                if(null == instance){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }

 new Thread(()->{
            LazySingleton instance3 = LazySingleton.getInstance();
            System.out.println(instance3);
        }).start();

        new Thread(() ->{
            LazySingleton instance4 = LazySingleton.getInstance();
            System.out.println(instance4);
        }).start();

结果:
com.junrui.designpattern.singleton.LazySingleton@4388eabf
com.junrui.designpattern.singleton.LazySingleton@4388eabf

volatile:禁止指令重排。创建对象正常的步骤为:1.分配空间;2.初始化;3.引用赋值,但是由于jit(编译器)或者CPU会对创建对象顺序进行优化,导致初始化和赋值的顺序颠倒。当第一个线程在132的过程中执行到了3,2还没有执行,第二个线程获取到了第一个线程执行到3,2还没有执行的对象   然后就返回了一个缺少初始化的对象,最后导致空指针。所以安全的代码需要加上volatile:使创建对象的顺序必须是  123.

class LazySingleton{
    private static volatile LazySingleton instance;
    private LazySingleton(){}

    public static  LazySingleton getInstance(){
        if (instance == null) {
            synchronized (LazySingleton.class){
                if(null == instance){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

new Thread(()->{
            LazySingleton instance3 = LazySingleton.getInstance();
            System.out.println(instance3);
        }).start();

        new Thread(() ->{
            LazySingleton instance4 = LazySingleton.getInstance();
            System.out.println(instance4);
        }).start();

饿汉式

静态变量在类加载的初始化阶段就完成了实例的初始化。本质上是借助jvm类加载机制,保证实例的唯一性。

类加载过程:

1.加载二进制数据到内存中,生成对应的class数据结构

2.链接:a.验证;b.准备(给类的静态成员变量赋默认值);c.解析(符号引号转为直接引用)

3.初始化:给类的静态变量赋初值

只有真正使用对应的类时,才会触发初始化 如(当前启动类即main函数所在类,直接进行new

操作,访问静态属性、访问静态方法,用反射访问类,初始化一个子类等等)

public class HungrySingletonTest {

    public static void main(String[] args) {
        HungrySingleton instance = HungrySingleton.getInstance();
        HungrySingleton instance2 = HungrySingleton.getInstance();
        System.out.println(instance2 == instance);//true
    }
}

class HungrySingleton{
    private static HungrySingleton instance = new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySingleton getInstance(){
        return instance;
    }
}

静态内部类

本质上是利用jvm类加载机制来保证线程安全

只有在实际使用时才会触发类的初始化,所以也是懒加载的一种。

当执行getInstance()方法时去初始化 InnerClassHolder静态内部类

public class InnerClassSingletonTest {
    public static void main(String[] args) {
        InnerClassSingleton instance1 = InnerClassSingleton.getInstance();
        InnerClassSingleton instance2 = InnerClassSingleton.getInstance();
        System.out.println(instance2 == instance1);//true

        new Thread(() ->{
            InnerClassSingleton instance3 = InnerClassSingleton.getInstance();
            System.out.println(instance3);
        }).start();
        new Thread(() ->{
            InnerClassSingleton instance4 = InnerClassSingleton.getInstance();
            System.out.println(instance4);
        }).start();
    }
}

class InnerClassSingleton{
    private static class InnerClassHolder{
        private static InnerClassSingleton instance = new InnerClassSingleton();
    }
    private InnerClassSingleton(){}
    public static InnerClassSingleton getInstance(){
        return InnerClassHolder.instance;
    }
}

结果:
com.junrui.designpattern.singleton.InnerClassSingleton@90472a2
com.junrui.designpattern.singleton.InnerClassSingleton@90472a2

枚举

public enum EnumSingleton {
    INSTANCE;

    private void print(){
        System.out.println(this.hashCode());
    }
}

class EnumTest{
    public static void main(String[] args) {
        EnumSingleton instance1 = EnumSingleton.INSTANCE;
        EnumSingleton instance2 = EnumSingleton.INSTANCE;
        System.out.println(instance2 == instance1);//true
    }
}

反序列化

反序列化违反单例模式

public class InnerClassSingletonTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        InnerClassSingleton instance1 = InnerClassSingleton.getInstance();

        ObjectOutputStream oos = new  ObjectOutputStream(Files.newOutputStream(Paths.get("testSerializable")));
        oos.writeObject(instance1);
        oos.close();


        ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Paths.get("testSerializable")));
        InnerClassSingleton instance2 = ((InnerClassSingleton) ois.readObject());
        System.out.println(instance2 == instance1);//false

    }
}
class InnerClassSingleton implements Serializable {
 static final long serialVersionUID = 42L;
    private static class InnerClassHolder{
        private static InnerClassSingleton instance = new InnerClassSingleton();
    }
    private InnerClassSingleton(){}
    public static InnerClassSingleton getInstance(){
        return InnerClassHolder.instance;
    }
}

在反序列化类里面添加Object readResolve()方法,就可以解决

public class InnerClassSingletonTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        InnerClassSingleton instance1 = InnerClassSingleton.getInstance();

        ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(Paths.get("testSerializable")));
        oos.writeObject(instance1);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Paths.get("testSerializable")));
        InnerClassSingleton instance2 = ((InnerClassSingleton) ois.readObject());
        System.out.println(instance2 == instance1);//true

    }
}

class InnerClassSingleton implements Serializable {
    static final long serialVersionUID = 42L;

    private static class InnerClassHolder{
        private static InnerClassSingleton instance = new InnerClassSingleton();
    }
    private InnerClassSingleton(){}
    public static InnerClassSingleton getInstance(){
        return InnerClassHolder.instance;
    }
    Object readResolve() throws ObjectStreamException{
        return InnerClassHolder.instance;
    }
}

工厂方法模式

简单工厂 

这是没有使用工厂的方法,当服务端类 Hamburger换成Hamburger2后客户端也得跟着换成Hamburger2,客户端就受到了服务端的影响,耦合度高,违反开闭原则。

//客户端
public class SimpleFactory {

    public static void main(String[] args) {
        Food food = new Hamburger();
        food.eat();
    }
}

//===============服务端==================================
interface  Food{
      public  void eat();
}


class  Hamburger implements Food{
    @Override
     public void eat() {
        System.out.println("吃汉堡包");
    }
}

class RiceNoodle implements Food{
    @Override
    public void eat() {
        System.out.println("吃过桥米线");
    }
}

使用简单工厂后,服务端改变后,不影响客户端的正常使用,耦合度低

public class SimpleFactory {

    public static void main(String[] args) {
        Food hamburger = FoodFactory.getGetFood(1);
        Food riceNoodle = FoodFactory.getGetFood(2);
        hamburger.eat();
        riceNoodle.eat();
    }
}
interface  Food{
      public  void eat();
}


class  Hamburger implements Food{
    @Override
     public void eat() {
        System.out.println("吃汉堡包");
    }
}

class RiceNoodle implements Food{
    @Override
    public void eat() {
        System.out.println("吃过桥米线");
    }
}

class FoodFactory{
    static Food getGetFood(int type){
        Food food = null;
        switch (type){
            case 1 :
                food = new Hamburger();
                break;
            case 2 :
                food = new RiceNoodle();
                break;
            default : break;
        }
        return food;
    }
}

优点:

       1.把具体产品的类型从客户端代码中解耦出来。

        2.服务端如果修改了具体的产品类名,客户端也知道。 

缺点:

        1.客户端不得不记住常量和具体产品的映射关系,比如:1对应汉堡包,2对应米线

        2.如果具体产品特别多那么简单工厂就会变得非常臃肿,比如有100个具体产品,则需要在简单工厂中的Switch中写100个case。

        3.最重要的是,如果需求有变化,客户端需要扩展具体产品的时候,则需要修改服务端简单工厂中的代码,违反“开闭原则”

工厂方法设计模式

public class Factory {
    public static void main(String[] args) {
        FoodFactory hamburgerFactory = new HamburgerFactory();
        Food hamburger = hamburgerFactory.getFood();
        hamburger.eat();
        FoodFactory riceNoodleFactory = new RiceNoodleFactory();
        Food riceNoodle = riceNoodleFactory.getFood();
        riceNoodle.eat();

    }
}
interface  Food{
    public  void eat();
}


class  Hamburger implements Food {
    @Override
    public void eat() {
        System.out.println("吃汉堡包");
    }
}

class RiceNoodle implements Food {
    @Override
    public void eat() {
        System.out.println("吃过桥米线");
    }
}

interface FoodFactory{
    public Food getFood();
}

class HamburgerFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new Hamburger();
    }
}
class RiceNoodleFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new RiceNoodle();
    }
}

当客户端想扩展时,只需要客户端操作就可以

//================客户端=============
public class Factory {
    public static void main(String[] args) {
        FoodFactory hamburgerFactory = new HamburgerFactory();
        Food hamburger = hamburgerFactory.getFood();
        hamburger.eat();
        FoodFactory riceNoodleFactory = new RiceNoodleFactory();
        Food riceNoodle = riceNoodleFactory.getFood();
        riceNoodle.eat();

        LpFactory lpFactory = new LpFactory();
        Food food = lpFactory.getFood();
        food.eat();

    }
}
class LpFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new Lp();
    }
}

class Lp implements Food{
    @Override
    public void eat() {
        System.out.println("西安凉皮真好吃");
    }
}

//=========================服务端========================
interface  Food{
    public  void eat();
}


class  Hamburger implements Food {
    @Override
    public void eat() {
        System.out.println("吃汉堡包");
    }
}

class RiceNoodle implements Food {
    @Override
    public void eat() {
        System.out.println("吃过桥米线");
    }
}

interface FoodFactory{
    public Food getFood();
}

class HamburgerFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new Hamburger();
    }
}
class RiceNoodleFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new RiceNoodle();
    }
}

优点:

        1.仍然具有简单工厂的优点,服务器端修改了具体的产品的类名以后,并不会影响到客户端。

        2.当客户端需要扩展一个新的产品时,不需要修改服务器端的代码,只需要在客户端扩展一个新的工厂。

缺点:

        如果有多个产品等级(Food就是一个产品等级),那么工厂类的数量就会爆炸式的增长。

工厂的名字是视为接口的,作者需要保证对外暴露的接口的名字是稳定的。也就是说,虽然客户端依赖于工厂的类名,但是工厂的名字都是趋向于稳定的。

既然新的产品时客户端扩展的,为什么不直接实例化对象?为什么需要让服务端去帮忙实现?

答:因为服务端在开发功能时不仅仅只会开发一些抽象产品、具体产品、对应的工厂,还会配套一些提前做好的框架。例如:

//================客户端=============
public class Factory {
    public static void main(String[] args) {
        FoodFactory hamburgerFactory = new HamburgerFactory();
        Food hamburger = hamburgerFactory.getFood();
        hamburger.eat();
        FoodFactory riceNoodleFactory = new RiceNoodleFactory();
        Food riceNoodle = riceNoodleFactory.getFood();
        riceNoodle.eat();

        LpFactory lpFactory = new LpFactory();
        Food lp = lpFactory.getFood();
        lp.eat();
        Business.taste(lpFactory);//Business方法为服务端中配套的框架,如果客户端新的产品是客户端自己创建的,而不是通过服务端创建的,那么就没法使用服务端配套的框架

    }
}
class LpFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new Lp();
    }
}

class Lp implements Food{
    @Override
    public void eat() {
        System.out.println("西安凉皮真好吃");
    }
}

//=========================服务端========================
interface  Food{
    public  void eat();
}


class  Hamburger implements Food {
    @Override
    public void eat() {
        System.out.println("吃汉堡包");
    }
}

class RiceNoodle implements Food {
    @Override
    public void eat() {
        System.out.println("吃过桥米线");
    }
}

interface FoodFactory{
    public Food getFood();
}

class HamburgerFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new Hamburger();
    }
}
class RiceNoodleFactory implements FoodFactory{
    @Override
    public Food getFood() {
        return new RiceNoodle();
    }
}

class Business{
    public static void taste(FoodFactory factory){
        Food food = factory.getFood();
        System.out.println("评委1,品尝");
        food.eat();
        Food food1 = factory.getFood();
        System.out.println("评委1,品尝");
        food1.eat();
        Food food2 = factory.getFood();
        System.out.println("评委1,品尝");
        food2.eat();
    }
}

uml类图

抽象工厂模式

目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 第2章 里氏替换原则 2.1 爱恨纠葛的父子关系 2.2 纠纷不断,规则压制 2.3 最佳实践 第3章 依赖倒置原则 3.1 依赖倒置原则的定义 3.2 言而无信,你太需要契约 3.3 依赖的三种写法 3.4 最佳实践 第4章 接口隔离原则 4.1 接口隔离原则的定义 4.2 美女何其多,观点各不同 4.3 保证接口的纯洁性 4.4 最佳实践 第5章 迪米特法则 5.1 迪米特法则的定义 5.2 我的知识你知道得越少越好 5.3 最佳实践 第6章 开闭原则 6.1 开闭原则的定义 6.2 开闭原则的庐山真面目 6.3 为什么要采用开闭原则 6.4 如何使用开闭原则 6.5 最佳实践 第二部分 我惹了谁——真刀实枪篇 第7章 单例模式 7.1 我是皇帝我独苗 7.2 单例模式的定义 7.3 单例模式的应用 7.4 单例模式的扩展 7.5 最佳实践 第8章 工厂方法模式 8.1 女娲造人的故事 8.2 工厂方法模式的定义 8.3 工厂方法模式的应用 8.3.1 工厂方法模式的优点 8.3.2 工厂方法模式的使用场景 8.4 工厂方法模式的扩展 8.5 最佳实践 第9章 抽象工厂模式 9.1 女娲的失误 9.2 抽象工厂模式的定义 9.3 抽象工厂模式的应用 9.3.1 抽象工厂模式的优点 9.3.2 抽象工厂模式的缺点 9.3.3 抽象工厂模式的使用场景 9.3.4 抽象工厂模式的注意事项 9.4 最佳实践 第10章 模板方法模式 10.1 辉煌工程—制造悍马 10.2 模板方法模式的定义 10.3 模板方法模式的应用 10.4 模板方法模式的扩展 10.5 最佳实践 第11章 建造者模式 11.1 变化是永恒的 11.2 建造者模式的定义 11.3 建造者模式的应用 11.4 建造者模式的扩展 11.5 最佳实践 第12章 代理模式 12.1 我是游戏至尊 12.2 代理模式的定义 12.3 代理模式的应用 12.3.1 代理模式的优点 12.3.2 代理模式的应用 12.4 代理模式的扩展 12.4.1 普通代理 12.4.2 强制代理 12.4.3 代理是有个性的 12.4.4 虚拟代理 12.4.5 动态代理 12.5 最佳实践 第13章 原型模式 13.1 个性化电子账单 13.2 原型模式的定义 13.3 原型模式的应用 13.3.1 原型模式的优点 13.3.2 原型模式的使用场景 13.4 原型模式的注意事项 13.4.1 构造函数不会被执行 13.4.2 浅拷贝和深拷贝 13.4.3 clone与final两个冤家 13.5 最佳实践 第14章 中介者模式 14.1 进销存管理是这个样子的吗? 14.2 中介者模式的定义 14.3 中介者模式的应用 14.4 中介者模式的实际应用 14.5 最佳实践 第15章 命令模式 15.1 项目经理也难当 15.2 命令模式的定义 15.3 命令模式的应用 15.3.1 命令模式的优点 15.3.2 命令模式的缺点 15.3.3 命令模式的使用场景 15.4 命令模式的扩展 15.4.1 未讲完的故事 15.4.2 反悔问题 15.5 最佳实践 第16章 责任链模式 16.1 古代妇女的枷锁—“三从四德” 16.2 责任链模式的定义 16.3 责任链模式的应用 16.3.1 责任链模式的优点 16.3.2 责任链模式的缺点 16.3.3 责任链模式的注意事项 16.4 最佳实践 第17章 装饰模式 17.1 罪恶的成绩单 17.2 装饰模式的定义 17.3 装饰模式应用 17.3.1 装饰模式的优点 17.3.2 装饰模式的缺点 17.3.3 装饰模式的应用 17.4 最佳实践 第18章 策略模式 18.1 刘备江东娶妻,赵云他容易吗 18.2 策略模式的定义 18.3 策略模式的应用 18.3.1 策略模式的优点 18.3.2 策略模式的缺点 18.3.3 策略模式的应用 18.3.4 策略模式的注意事项 18.4 策略模式的扩展 18.5 最佳实践 第19章 适配器模式 19.1 业务发展—上帝才能控制 19.2 适配器模式的定义 19.3 适配器模式的应用 19.3.1 适配器模式的优点 19.3.2 适配器模式的应用 19.3.3 适配器模式的注意事项 19.4 适配器模式的扩展 19.5 最佳实践 第20章 迭代器模式 20.1 整理项目信息—苦差事 20.2 迭代器模式的定义 20.3 迭代器模式的应用 20.4 最佳实践 第21章 组合模式 21.1 公司的人事架构是这样的吗 21.2 组合模式的定义 21.3 组合模式的应用 21.3.1 组合模式的优点 21.3.2 组合模式的缺点 21.3.3 组合模式的应用 21.3.4 组合模式的注意事项 21.4 组合模式的扩展 21.4.1 真实的组合模式 21.4.2 透明的组合模式 21.4.3 组合模式的遍历 21.5 最佳实践 第22章 观察者模式 22.1 韩非子身边的卧底是谁派来的 22.2 观察者模式的定义 22.3 观察者模式的应用 22.3.1 观察者模式的优点 22.3.2 观察者模式的缺点 22.3.3 观察者模式的应用 22.3.4 观察者模式的注意事项 22.4 观察者模式的扩展 22.4.1 Java世界中的观察者模式 22.4.2 项目中真实观察者模式 22.4.3 订阅发布模型 22.5 最佳实践 第23章 门面模式 23.1 我要投递信件 23.2 门面模式的定义 23.3 门面模式的应用 23.3.1 门面模式的优点 23.3.2 门面模式的缺点 23.3.3 门面模式的应用 23.4 门面模式的注意事项 23.4.1 一个子系统可以有多个门面 23.4.2 门面不参与子系统内的业务逻辑 23.5 最佳实践 第24章 备忘录模式 24.1 如此追女孩子,你还不乐 24.2 备忘录模式的定义 24.3 备忘录模式的应用 24.3.1 备忘录模式的应用 24.3.2 备忘录模式的注意事项 24.4 备忘录模式的扩展 24.4.1 clone方式的备忘录 24.4.2 多状态的备忘录模式 24.4.3 多备份的备忘录 24.4.4 封装得更好一点 24.5 最佳实践 第25章 访问者模式 25.1 员工的隐私何在? 25.2 访问者模式的定义 25.3 访问者模式的应用 25.3.1 访问者模式的优点 25.3.2 访问者模式的缺点 25.3.3 访问者模式的应用 25.4 访问者模式的扩展 25.4.1 统计功能 25.4.2 多个访问者 25.4.3 双分派 25.5 最佳实践 第26章 状态模式 26.1 城市的纵向发展功臣—电梯 26.2 状态模式的定义 26.3 状态模式的应用 26.3.1 状态模式的优点 26.3.2 状态模式的缺点 26.3.3 状态模式的应用 26.3.4 状态模式的注意事项 26.4 最佳实践 第27章 解释器模式 27.1 四则运算你会吗 27.2 解释器模式的定义 27.3 解释器模式的应用 27.3.1 解释器模式的优点 27.3.2 解释器模式的缺点 27.3.3 解释器模式使用的场景 27.3.4 解释器模式的注意事项 27.4 最佳实践 第28章 享元模式 28.1 内存溢出,司空见惯 28.2 享元模式的定义 28.3 享元模式的应用 28.3.1 享元模式优点和缺点 28.3.2 享元模式的应用 28.4 享元模式的扩展 28.4.1 线程安全的问题 28.4.2 性能平衡 28.5 最佳实践 第29章 桥梁模式 29.1 我有一个梦想…… 29.2 桥梁模式的定义 29.3 桥梁模式的应用 29.3.1 桥梁模式的优点 29.3.2 桥梁模式的应用 29.3.3 桥梁模式的注意事项 29.4 最佳实践 第三部分 谁的地盘谁做主—模式PK篇 第30章 创建类模式大PK 30.1 工厂方法模式VS建造者模式 30.1.1 按工厂方法建造超人 30.1.2 按建造者模式建造超人 30.1.3 最佳实践 30.2 抽象工厂模式VS建造者模式 30.2.1 按抽象工厂模式生产车辆 30.2.2 按建造者模式生产车辆 30.2.3 最佳实践 第31章 结构类模式大PK 31.1 代理模式VS装饰模式 31.1.1 代理模式 31.1.2 装饰模式 31.1.3 最佳实践 31.2 装饰模式VS适配器模式 31.2.1 按装饰模式描述丑小鸭 31.2.2 按适配器模式实现丑小鸭 31.2.3 最佳实践 第32章 行为类模式大PK 32.1 命令模式VS策略模式 32.1.1 策略模式实现压缩算法 32.1.2 命令模式实现压缩算法 32.1.3 小结 32.2 策略模式VS状态模式 32.2.1 策略模式实现人生 32.2.2 状态模式实现人生 32.2.3 小结 32.3 观察者模式VS责任链模式 32.3.1 责任链模式实现DNS解析过程 32.3.2 触发链模式实现DNS解析过程 32.3.3 小结 第33章 跨战区PK 33.1 策略模式VS桥梁模式 33.1.1 策略模式实现邮件发送 33.1.2 桥梁模式实现邮件发送 33.1.3 最佳实践 33.2 门面模式VS中介者模式 33.2.1 中介者模式实现工资计算 33.2.2 门面模式实现工资计算 33.2.3 最佳实践 33.3 包装模式群PK 33.3.1 代理模式 33.3.2 装饰模式 33.3.3 适配器模式 33.3.4 桥梁模式 33.3.5 最佳实践 第四部分 完美世界—混编模式 第34章 命令模式+责任链模式 34.1 搬移UNIX的命令 34.2 混编小结 第35章 工厂方法模式+策略模式 35.1 迷你版的交易系统 35.2 混编小结 第36章 观察者模式+中介者模式 36.1 事件触发器的开发 36.2 混编小结 第37章 规格模式 37.1 规格模式的实现 37.2 最佳实践 第38章 MVC框架 38.1 MVC框架的实现 38.1.1 MVC的系统架构 38.1.2 模型管理器 38.1.3 值栈 38.1.4 视图管理器 38.1.5 工具类 38.2 最佳实践 附录:23个设计模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值