浅谈设计模式(一)

四大件——计算机网络、计算机操作系统、数据结构和算法、设计模式。而这篇文章,针对常见的几种设计模式,展开讨论,若是讨论的过浅,或者是有不对的地方,还望各位大佬多多指正。

一、设计模式的五大基本原则

1、开放封闭原则

我们的类,对于扩展应该是开放的,对于修改是封闭的。也就是说,我们支持类继承、组合等扩展方式,让类具有更多的特性,但是不能直接对类进行修改。

2、单一职责原则

单一职责,指的是一个类的变化,往往只有一个变化点,能够使类的状态发送变化,且这个变化点的方向,也就是这个类的职责所在。

3、里式替换原则

这是一个契合于多态的原则,一个类的子类,可以直接代替其父类。接口实现类应该可以对接口进行代替。

4、依赖倒置原则

高层模块不应该直接依赖于底层模块,因为两者都是变化点,两者都应该依赖于抽象
具体实现细节应该依赖于抽象

5、接口隔离原则

接口应该小而完备,那些不需要的方法,不应该强迫子类去实现

二、模板方法

这是一种组件协作模式,定义程序的执行流程,而流程的具体实现,应该延迟到子类去实现,这样子就可以在不改变父类原有流程的基础上,对父类的方法做具体实现(重载)。

1. 父类:

package templateMethod;

/**
 * @author yishuai
 * @version 1.0
 * @description 父类
 * @date 2021/10/7 16:11
 */
public abstract class Father {

    public void step1(){
        System.out.println("步骤一");
    }
    public void step2(){
        System.out.println("步骤二");
    }
    public void step3(){
        System.out.println("步骤三");
    }
    public abstract void step4();
    public abstract void step5();

    /**
     * 定义好执行过程,由子类确定实现逻辑
     */
    public void run(){
        //稳定点
        step1();
        step2();
        step3();
        //变化点
        step4();
        step5();
    }
}

2. 子类

package templateMethod;

/**
 * @author yishuai
 * @version 1.0
 * @description 子类
 * @date 2021/10/7 16:16
 */
public class Son extends Father{

    //两个具体实现细节
    @Override
    public void step4() {
        System.out.println("步骤4");
    }

    @Override
    public void step5() {
        System.out.println("步骤5");
    }
}

3. 测试类

package templateMethod;

/**
 * @author yishuai
 * @version 1.0
 * @description 测试类
 * @date 2021/10/7 16:18
 */
public class Test {

    public static void main(String[] args) {
        //用父类定义具体的执行流程,对应的子类实例去实现
        Father father = new Son();
        father.run();
    }
}

三、单例模式

手写五种单例模式,基本常考一种,会五种更强
主要思想:
1、私有化构造器
2、自行创建实例
3、对外暴露获取这个实例的方式

1. 饿汉式(线程安全)

package single;

/**
 * @author yishuai
 * @version 1.0
 * @description 懒汉式
 * @date 2021/10/7 16:24
 */
public class Demo01 {
    /**
     * 设置成private是保证其他类不能直接获取
     * 设置成static是为了初始类就立即实例化
     * 因为是随着类加载而实例化,所以是线程安全的,因为类加载只会发生一次
     */
    private static Demo01 demo01 = new Demo01();

    //构造器私有化
    private Demo01() {
    }
    //直接返回实例
    public static Demo01 getInstance(){
        return demo01;
    }
}

2. 懒汉式(线程不安全)

package single;

/**
 * @author yishuai
 * @version 1.0
 * @description 懒汉式
 * @date 2021-10-7 16:30:56
 */
public class Demo02 {
    /**
     * 设置成private是保证其他类不能直接获取
     * 设置成static是为了让getInstance方法直接调用
     */
    private static Demo02 demo02;

    //构造器私有化
    private Demo02() {
    }
    
    //直接返回实例,此时是线程不安全的,若要改造成线程安全,则需要在这个方法上面加上sync锁
    public static Demo02 getInstance(){
        //如果还没实例化,就进行实例化
        if (demo02 == null){
            demo02 = new Demo02();
        }
        return demo02;
    }
}

3. 内部类(线程安全)

package single;

/**
 * @author yishuai
 * @version 1.0
 * @description 内部类
 * @date 2021/10/7 16:34
 */
public class Demo03 {
    
    //构造器私有化
    private Demo03() {
    }

    /**
     * 通过一个静态的内部类的方式,成为Demo03的一个类属性
     * 保证全局只有一个实例
     */
    private static class insideSingle{
        //实例化为静态常量,保证全局单一,且方便外部类调用
        private static final Demo03 demo03 = new Demo03();
    }
    
    //直接返回实例
    public static Demo03 getInstance(){
        return insideSingle.demo03;
    }
}

4. 枚举(线程安全)

package single;

/**
 * @author yishuai
 * @version 1.0
 * @description 枚举
 * @date 2021/10/7 16:42
 */
public enum Demo04 {
    /**
     * 枚举本身就是一个全局单实例
     * 它是由JVM保证的
     * 每个属性都会被 public static final修饰
     */
    DEMO04;
    public void xxx(){
        //这里写业务逻辑,jvm初始化并保证全局单例,不可被二次初始化
    }
}

5. 双重锁校验(线程安全)

package single;

/**
 * @author yishuai
 * @version 1.0
 * @description 双重锁校验
 * @date 2021/10/7 16:49
 */
public class Demo05 {
    /**
     * 设置成private是保证其他类不能直接获取
     * 设置成static是为了让getInstance方法直接调用,且全局单一
     * 设置成volatile是为了保证可见性,防止因为高速缓存,造成死锁
     */
    private volatile static Demo05 demo05;

    //构造器私有化
    private Demo05() {
    }
    
    public static Demo05 getInstance(){
        /*
            让所有线程都能立即判断demo05是否为空,
            这样子当demo05实例化之后,就不用去获取锁了,效率更高
         */
        if (demo05 == null){
            //在内部加锁,是为了防止多个线程同时争抢,造成多次实例化
            synchronized (Demo05.class){
                /*
                    再次判断是因为多个线程在争抢锁,
                    可能会在实例化之前,多个线程有序的进入
                    再次判断就可以让其他线程不会再次对Demo05实例化
                 */
                if (demo05 == null){
                    demo05 = new Demo05();
                }
            }
        }
        return demo05;
    }

}

四、策略模式

通过策略模式,将程序设计的骨架,通过多态的方式,在需要的场合,在各个类型直接切换,实现对应的算法逻辑,以此来解决大量判断的问题,便于拓展,缺点是会增加许多类。

1. 抽象接口

package strategy;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:07
 */
public interface People {
    /**
     * 通过接口定义方法,让子类去实现,
     * 通过多态绑定对应的子类,调用对应的业务逻辑
     */
    public void eat();

    public void sleep();
}

2. 黑人

package strategy;

/**
 * @author yishuai
 * @version 1.0
 * @description 黑人
 * @date 2021年10月7日17:10:06
 */
public class BlackPeople implements People{

    @Override
    public void eat() {
        System.out.println("我是小黑人,我要吃饭了");
    }

    @Override
    public void sleep() {
        System.out.println("我是小黑人,我要睡觉觉了");
    }
}

3. 白人

package strategy;

/**
 * @author yishuai
 * @version 1.0
 * @description 白人
 * @date 2021/10/7 17:09
 */
public class WhitePeople implements People{

    @Override
    public void eat() {
        System.out.println("我是小白人,我要吃饭了");
    }

    @Override
    public void sleep() {
        System.out.println("我是小白人,我要睡觉觉了");
    }
}

4. 中间类

package strategy;

/**
 * @author yishuai
 * @version 1.0
 * @description 中间类
 * @date 2021/10/7 17:12
 */
public class Proxy {
    //父类
    private People people;

    //子类绑定父类
    public Proxy(People people) {
        this.people = people;
    }
    //通过父类调优,实际为子类具体逻辑
    public void run(){
        people.eat();
        people.sleep();
    }
}

5. 测试

package strategy;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:10
 */
public class Test {
    public static void main(String[] args) {
        //通过中间类,传入的是什么颜色的人,就会调用什么方法
        Proxy proxy = new Proxy(new BlackPeople());
        proxy.run();
    }

}

五、工厂模式

这是一种对象创建模式,通过这种模式,避免直接去new对象,而是通过工厂来获取对应的对象实例,从而实现代码的解耦

1. 人接口

package factory;

/**
 * @author yishuai
 * @version 1.0
 * @description 人接口
 * @date 2021/10/7 17:20
 */
public interface People {
    public void eat();
}

2. 黑人

package factory;

/**
 * @author yishuai
 * @version 1.0
 * @description 黑人
 * @date 2021/10/7 17:21
 */
public class BlackPeople implements People{

    @Override
    public void eat() {
        System.out.println("小黑吃饭了");
    }
}

3. 白人

package factory;

/**
 * @author yishuai
 * @version 1.0
 * @description 白人
 * @date 2021/10/7 17:21
 */
public class WhitePeople implements People{

    @Override
    public void eat() {
        System.out.println("小白吃饭了");
    }
}

4. 工厂

package factory;

/**
 * @author yishuai
 * @version 1.0
 * @description 造人工厂
 * @date 2021/10/7 17:22
 */
public class PeopleFactory {

    //返回黑人
    public People getBlackPeople(){
        return new BlackPeople();
    }
    
    //返回白人
    public People getWhitePeople(){
        return new WhitePeople();
    }
}

5. 测试

package factory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:24
 */
public class Test {
    public static void main(String[] args) {
        //创建工厂
        PeopleFactory peopleFactory = new PeopleFactory();
        //拿到黑人实例并吃饭
        peopleFactory.getBlackPeople().eat();
        //拿到白人实例并吃饭
        peopleFactory.getWhitePeople().eat();
    }

}

六、抽象工厂模式

抽象工厂模式又被称之为超级工厂模式,这是一个创造工厂的工厂,它返回的应该是其他实例的工厂,然后由这个工厂创建实例。

1. 借用上面的工厂模式代码,完全拷贝到新的包中

2. 创建动物接口

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description 动物接口
 * @date 2021/10/7 17:32
 */
public interface Animal {
    public void sleep();
}

3. 猫

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:34
 */
public class Cat implements Animal {

    @Override
    public void sleep() {
        System.out.println("猫咪睡觉觉了");
    }
}

4. 狗

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:34
 */
public class Dog implements Animal {

    @Override
    public void sleep() {
        System.out.println("狗狗睡觉觉了");
    }
}

5. 动物工厂

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:35
 */
public class AnimalFactory {
    //获取猫实例
    public Animal getCat(){
        return new Cat();
    }

    //获取狗实例
    public Animal getDog(){
        return new Dog();
    }

}

6. 抽象工厂

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:36
 */
public class AbstractFactory {

    //获取动物实例工厂
    public AnimalFactory getAnimalFactory(){
        return new AnimalFactory();
    }

    //获取人实例工厂
    public PeopleFactory getPeopleFactory(){
        return new PeopleFactory();
    }

}

7. 测试

package abstractFactory;

/**
 * @author yishuai
 * @version 1.0
 * @description TODO
 * @date 2021/10/7 17:24
 */
public class Test {
    public static void main(String[] args) {
        //创建抽象工厂
        AbstractFactory abstractFactory = new AbstractFactory();

        //通过抽象工厂拿到造人工厂
        PeopleFactory peopleFactory = abstractFactory.getPeopleFactory();
        //通过造人创建造一个白人,让他吃饭
        peopleFactory.getWhitePeople().eat();
        //通过造人创建造一个黑人,让他吃饭
        peopleFactory.getBlackPeople().eat();

        //通过抽象工厂拿到动物工厂
        AnimalFactory animalFactory = abstractFactory.getAnimalFactory();
        //通过动物工厂造一只猫,让它睡觉
        animalFactory.getCat().sleep();
        //通过动物工厂造一只狗,让它睡觉
        animalFactory.getDog().sleep();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种面向对象的编程语言设计模式可以帮助我们更好地编写面向对象的代码。在JavaWeb项目中,设计模式可以帮助我们解决一些常见的问题,比如复杂的业务逻辑、代码重用、可扩展性等等。 下面是一些常见的设计模式JavaWeb项目中的使用: 1. MVC模式:MVC模式是一种常见的设计模式,它将应用程序分为三个部分:模型、视图和控制器。在JavaWeb项目中,我们可以使用MVC模式来分离业务逻辑和用户界面,并且可以更容易地进行修改和维护。 2. 工厂模式:工厂模式是一种创建型设计模式,它可以帮助我们更好地组织代码并提高代码的可复用性。在JavaWeb项目中,我们可以使用工厂模式来创建对象,并且可以根据需要动态地创建不同的对象。 3. 单例模式:单例模式是一种创建型设计模式,它保证了一个类只有一个实例,并提供了一个全局访问点。在JavaWeb项目中,我们可以使用单例模式来管理共享资源,比如数据库连接池。 4. 观察者模式:观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖对象都会得到通知并自动更新。在JavaWeb项目中,我们可以使用观察者模式来实现事件驱动的编程。 5. 装饰器模式:装饰器模式是一种结构型设计模式,它允许我们动态地添加或修改一个对象的功能。在JavaWeb项目中,我们可以使用装饰器模式来扩展一个类的功能,而不需要修改它的原始代码。 当然,在JavaWeb项目中还有很多其他的设计模式可以使用,具体使用哪些设计模式需要根据具体的情况而定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值