设计模式(一)--编程界的九阳神功

在学习设计模式前,我们先要弄明白一个问题,那就是为什么要学习设计模式?在JAVA领域,大部分使用的是贫血模型,业务逻辑都是service之间的调用,类似于函数式编程,其他高深的东西都封装于框架中,平时能用上设计模式的地方确实不多,似乎学习了也没啥用。

我觉得设计模式特别像九阳神功,练成「九阳神功」后,内力自生速度奇快,无穷无尽,普通拳脚也能使出绝大攻击力,学习了设计模式,虽然还是普通的功能,却在稳定性,可维护性上大不相同了。

九阳神功是融会贯通武学体系,练成后天下武学皆附拾可用。学会了设计模式,再看各种开源框架源码,就能融会贯通,明白作者为什么要这么写,并且为已所用。

设计模式总览

 七大设计原则

开闭原则,软件实体应当对扩展开放,对修改关闭,扩展新类而不是修改旧类

里氏替换原则,继承必须确保超类所拥有的性质在子类中仍然成立,继承父类而不去改变父类

依赖倒置原则,高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象,面向接口编程,而不是面向实现类

单一职责原则,一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分,每个类只负责自己的事情,而不是变成万能

接口隔离原则,一个类对另一个类的依赖应该建立在最小的接口上,各个类建立自己的专用接口,而不是建立万能接口

迪米特法则,只与你的直接朋友交谈,不跟“陌生人”说话,无需直接交互的两个类,如果需要交互,使用中间者

合成复用原则,软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

单例模式

一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。

单例特点

某个类只能有一个实例;(构造器私有)

它必须自行创建这个实例;(自己编写实例化逻辑)

它必须自行向整个系统提供这个实例;(对外提供实例化方法)

使用场景

多线程中的线程池

数据库的连接池

系统环境信息

上下文(ServletContext) ......

接下去看下经典的懒汉模式的单例代码

public class SingleObject {
    //使用volatile保证内存可见性,防止指令重排
    private volatile static SingleObject instance;

    //私有构造器,外部无法new
    private SingleObject() {

    }

    public static SingleObject getInstance() {
        //判断是否已有实例,没有则创建实例
        if (instance == null) {
            //多线程情况下需要加锁
            synchronized (SingleObject.class) {
                //防止多个线程走到这里,所以还需要判断一次
                if (instance == null) {
                    instance = new SingleObject();
                }
            }
        }
        return instance;
    }
}

工厂模式

提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可。难点:写好我们的工厂

简单工厂

简单工厂的核心代码就是MouseFactory的createMouse,通过传入不同的type来返回不同的Mouse

 

public abstract class Mouse {
    public abstract void sayHi();

    public void test() {
        System.out.println("测试工作");
    }
}

public class DellMouse extends Mouse {
    @Override
    public void sayHi() {
        System.out.println("DellMouse");
    }
}

public class HpMouse extends Mouse {
    @Override
    public void sayHi() {
        System.out.println("HpMouse");
    }
}

public class SimpleMouseFactory {
    //创建mouse对象
    public static Mouse createMouse(int type) {
        Mouse mouse = null;
        if (type == 0) {
            mouse = new DellMouse();
        } else if (type == 1) {
            mouse = new HpMouse();
        } else {
            throw new IllegalArgumentException();
        }
        //出厂测试
        mouse.test();
        return mouse;
    }

    @Test
    public void testCreate() {
        Mouse mouse = createMouse(0);
        mouse.sayHi();
        mouse = createMouse(1);
        mouse.sayHi();
    }
}

现在思考一个问题,为什么要用工厂模式,而不是直接new一个HpMouse或者DellMouse呢?

首先,根据依赖倒置原则,我们应该依赖抽象,而不是具体的类,直接new一个就是依赖于具体的类了。其次工厂模式可以在产品出厂前做一些特殊处理,比如测试工作,这个很重要,Spring的很多重要功能都依赖于此。我们知道Spring里面有个bean工厂,而它生产的不是原始对象,而是代理对象,只有通过代理对象才能实现面向切面编程,后面的拦截器,事务处理等才有了实现的可能。理解了上面两点,也就理解了工厂模式。

简单工厂有个缺点就是如果添加新的产品,需要修改createMouse方法,也就违反了开闭原则。这个时候就可以使用工厂模式。

工厂模式

工厂模式就是把MouseFactory作为抽象类,每一种产品都新建一个工厂类,一个工厂类只生成一种产品,这样当有新的产品时,只需要新建一个工厂类就行了。

 

public abstract class MouseFactory {
    public abstract Mouse createMouse();

    static class HpMouseFactory extends MouseFactory {

        @Override
        public Mouse createMouse() {
            return new HpMouse();
        }
    }

    static class DellMouseFactory extends MouseFactory {

        @Override
        public Mouse createMouse() {
            return new DellMouse();
        }
    }

    public static void main(String[] args) {
        HpMouseFactory hpMouseFactory = new HpMouseFactory();
        DellMouseFactory dellMouseFactory = new DellMouseFactory();
        Mouse mouse = hpMouseFactory.createMouse();
        mouse.sayHi();
        mouse = dellMouseFactory.createMouse();
        mouse.sayHi();
    }
}

抽象工厂模式

工厂模式有个限制就是只能生产一类的产品,如果想又生产鼠标又生产键盘该怎么办呢?这时就要用到抽象工厂了,把生产鼠标和键盘的方法放在抽象工厂类中,下面的实现类来决定具体生产哪一种产品。

 

public abstract class PcFactory {
    abstract Mouse createMouse();

    abstract Keybo createKeybo();

    static class HpFactory extends PcFactory {
        @Override
        Mouse createMouse() {
            return new HpMouse();
        }

        @Override
        Keybo createKeybo() {
            return new HpKeybo();
        }
    }

    static class DellFactory extends PcFactory {
        @Override
        Mouse createMouse() {
            return new DellMouse();
        }

        @Override
        Keybo createKeybo() {
            return new DellKeybo();
        }
    }

    public static void main(String[] args) {
        DellFactory dellFactory = new DellFactory();
        Mouse mouse = dellFactory.createMouse();
        mouse.sayHi();
        Keybo keybo = dellFactory.createKeybo();
        keybo.sayHi();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值