Java中23中设计模式(一)

目录

1、单例模式

2、策略模式

 工厂模式

3、工厂方法模式

4、抽象工厂模式

5、门面模式

6、调停者模式

7、装饰者模式

8、责任链模式

参考文献


1、单例模式

  就是在项目中只需要一个实例存在,下面列出了几个单例模式的写法

饿汉式
/**
 * 单例模式 饿汉式
 */
public class Singleton01 {
    //首先定义一个静态的实例
    private final static Singleton01 INSTANCE = new Singleton01();
    //然后把构造方法私有化
    private Singleton01() {
    }

    public static Singleton01 getInstance() {
        return INSTANCE;
    }
}
懒汉式
/**
 * 单例模式 懒汉式
 * 这个多线程中同时调用的时候会有问题
 * 解决办法就是 使用 synchronized 加锁
 * 但是这样虽然解决了多线程的问题,效率会大大降低
 * 优化了一下,就是锁住代码块,
 * 注意:方法中有两个判断,是有必要的,这个是为了
 */
public class Singleton04 {
    //首先定义一个静态的实例
    private static volatile Singleton04 INSTANCE;

    //然后把构造方法私有化
    private Singleton04() {
    }

    //使用的时候才加载
    public static synchronized Singleton04 getInstance() {
        //注意:这里的两个判断是有必要的,第一个判断是为了
        //如果不为空,就不用加锁,加快了效率
        if (INSTANCE == null) {
            synchronized (Singleton04.class) {
                if (INSTANCE == null) {
                    //为了测试,休眠1毫秒
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton04();
                }
            }
        }
        return INSTANCE;
    }


}
静态内部类
/**
 * 静态内部类的方式
 * 这个是完美的写法之一
 * 线程安全是由jvm来保证的,
 * 虚拟机加载class的时候只加载一次,所以Sl06Holder也只加载一次
 * 所以INSTANCE也只加载一次,所以也不用加锁
 */
public class Singleton06 {
    //首先把构造方法私有化
    private Singleton06() {
    }
    //然后定义一个静态内部类
    private static class Sl06Holder {
        //初始化了Singleton06
        private final static Singleton06 INSTANCE = new Singleton06();
    }
    public static Singleton06 getInstance() {
        return Sl06Holder.INSTANCE;
    }
    
}
枚举单例
/**
 * 使用枚举类 不仅可以解决线程同步
 * 还可以防止反序列化
 * 枚举单例
 * 这种也是完美的写法之一
 */
public enum Singleton07 {

    INSTANCE;
    //业务方法
    public void test(){
    }

}
2、策略模式

  策略模式封装的就是做一件事情的不同的执行方式,用的最多的就是Collections.sort()方法,里面实现Comparator接口来进行排序,下面咱们模仿Comparator 来演示策略模式。

  比如,现在有一个学生的实体类,需要根据年龄、身高、体重、分数等条件分别进行排序,这个时候,使用策略模式来实现的话,就比较好

1. 首先是定义一个接口Comparator
public interface Comparator<T> {
    int compare(T o1, T o2);
}
2. 写一个排序的方法 Sorter
public class Sorter {
    //使用选择排序的方法,把数据进行排序
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        for (int i = 0; i < list.size(); i++) {
            int min = i;
            for (int j = i + 1; j < list.size(); j++) {
                min = c.compare(list.get(j), list.get(min)) == -1 ? j : min;
            }
            swap(list, i, min);
        }
    }

    private static <T> void swap(List<T> list, int i, int min) {
        T temp = list.get(i);
        list.set(i, list.get(min));
        list.set(min, temp);
    }


    public static <T> void insort(T[] ts, Comparator<? super T> c) {
        for (int i = 0; i < ts.length; i++) {
            int min = i;
            for (int j = i + 1; j < ts.length; j++) {
                min = c.compare(ts[j], ts[min]) == -1 ? j : min;
            }
            swap(ts, i, min);
        }
    }


    private static <T> void swap(T[] ts, int i, int min) {
        T temp = ts[i];
        ts[i] = ts[min];
        ts[min] = temp;
    }

}

3. 然后写个类实现Comparator接口,比如身高,其他的原理一样,在这里我就不写了。
public class HeightComparator implements Comparator<Student> {
    //根据判断学生的身高来进行排序
    //从小到大
    @Override
    public int compare(Student o1, Student o2) {
        if (o1.getHeight() > o2.getHeight()) return 1;
        else if (o1.getHeight() < o2.getHeight()) return -1;
        return 0;
    }
}
4. 测试
public class Test2 {

    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("张三", 34, 70.5, 178, 87));
        list.add(new Student("李四", 45, 88.5, 187, 65));
        list.add(new Student("王五", 23, 98.5, 180, 89));
        //根据年龄排序
        Sorter.sort(list, (o1, o2) -> {
            if (o1.getAge() > o2.getAge()) return 1;
            else if (o1.getAge() < o2.getAge()) return -1;
            else return 0;
        });

        System.out.println("年龄:" + list.toString());

        //根据体重排序
        Sorter.sort(list,new WeightComparator());
        System.out.println("体重:" + list.toString());
        //根据身高排序
        Sorter.sort(list, new HeightComparator());
        System.out.println("身高:" + list.toString());
        //根据分数排序
        //也可以通过Java1.8中的Lambda表达式来完成
        Sorter.sort(list, (o1, o2) -> {
            if (o1.getScore() > o2.getScore()) return 1;
            else if (o1.getScore() < o2.getScore()) return -1;
            else return 0;
        });
        System.out.println("分数:" + list.toString());
    }

}
工厂模式

定义:

  任何可以产生对象的方法或类,都可以称之为工厂,单例也是一种工厂,数据静态工厂

3、工厂方法模式

以下是用到的类
Java中23中设计模式(一)_第1张图片
产品代码如下:

//产品接口,产品都需要实现这个接口
public interface Moveable {
    void go();
}
//汽车 实现 Moveable接口
public class Car implements Moveable {
    @Override
    public void go() {
        System.out.println("car go...");

    }
}
//飞机 实现 Moveable接口
public class Plane implements Moveable {

    @Override
    public void go() {
        System.out.println("plane flying...");

    }
}

工厂代码如下:

/**
 * 汽车工厂
 */
public class CarFactory {

    public static Car create() {
        System.out.println("a car created");
        return new Car();
    }
}
/**
 * 飞机工厂
 */
public class PlaneFactory {

    public static Plane create() {
        System.out.println("a Plane created");
        return new Plane();
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Moveable m1 = CarFactory.create();
        m1.go();
        Moveable m2 = PlaneFactory.create();
        m2.go();
    }
}

运行结果如下:

Java中23中设计模式(一)_第2张图片

4、抽象工厂模式

  抽象工厂是对工厂方法模式进行抽象

例子需要的类如下:

Java中23中设计模式(一)_第3张图片

产品的抽象类如下

/**
 * 食物抽象方法
 */
public abstract class Food {
    public abstract void Fname();
}

/**
 * 交通工具的抽象类
 */
public abstract class Vehicle {
    public abstract void go();
}

/**
 * 武器的抽象类
 */
public abstract class Weapon {
    public abstract void shoot();
}

工厂的抽象类如下:

/**
 * 抽象工厂
 */
public abstract class abstracFactory {

    public abstract Vehicle createVehicle();

    public abstract Weapon createWeapon();

    public abstract Food createFood();

}

产品的实现类如下:

//AK47 继承 Weapon
public class AK47 extends Weapon {
    @Override
    public void shoot() {
        System.out.println("用的武器是 AK47");
    }
}
//汽车 继承 Vehicle
public class Car extends Vehicle {
    @Override
    public void go() {
        System.out.println("交通工具是 汽车");
    }
}
//面包 继承 Food
public class Bread extends Food {
    @Override
    public void Fname() {
        System.out.println("食物是 面包");
    }
}

工厂的实现类如下:

public class ModernFactory extends abstracFactory {
    @Override
    public Vehicle createVehicle() {
        return new Car();
    }

    @Override
    public Weapon createWeapon() {
        return new AK47();
    }

    @Override
    public Food createFood() {
        return new Bread();
    }
}

测试类如下:

public class Test {
    public static void main(String[] args) {
        abstracFactory af = new ModernFactory();
        Food food = af.createFood();
        food.Fname();
        Vehicle vehicle = af.createVehicle();
        vehicle.go();
        Weapon weapon = af.createWeapon();
        weapon.shoot();
    }
}

测试结果:
Java中23中设计模式(一)_第4张图片

5、门面模式

  门面模式(Facade),是指提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使得子系统更容易使用。

  通俗的讲就是在外部调用内部模块之间声明一个门面Facade 用来管理,就是外部只访问这个门面类,这个门面类去访问内部的各个模块。如下图所示:

Java中23中设计模式(一)_第5张图片

6、调停者模式

  调停者模式(Mediator)是软件设计模式的一种,用于模块间解耦,通过避免对象互相显式的指向对方从而降低耦合。

  通俗的讲就是由于代码中各个模块之间需要调用,然后声明一个调停者,然后内部的代码模块之间不直接访问,模块都直接访问调停者,然后调停者向指定模块获取数据,然后把数据再返回指定模块,如下图所示:
Java中23中设计模式(一)_第6张图片  一般门面和调停者模式配合使用,就是定义一个模块。对于外部而言就是门面者,对于内部模块而言就是调停者,如下图:

Java中23中设计模式(一)_第7张图片

7、装饰者模式

定义: 装饰者模式又被称作包装模式,就是在不改变原类文件和不使用继承的情况下,动态的给已知对象添加一些额外的功能,添加的功能还可以手动撤销。

组成部分:

1. 抽象组件(Component): 给出一个抽象接口,以规范准备接收附件功能的对象。

2. 被装饰者(ConcreteComponent): 抽象组件的具体实现类。

3. 装饰者组件(Decoretor): 自己实现了抽象组件,并且持有实现了抽象组件的实例的引用,该类的职责就是为了装饰具体组件对象,定义为具体装饰者的基类。

4. 具体装饰(ConcreteDecoretor) 是装饰者组件的具体实现类,是负责给被装饰者添加附加功能的。

结构图如下:

Java中23中设计模式(一)_第8张图片

举例:

  我们以火锅为例子。我们都知道,我们去吃火锅,我们先选锅底,有麻辣的,香辣的,番茄的等等。选完锅底以后,我们再选菜,菜有牛肉,羊肉,土豆片,鱼丸等。根据以上思路,我们可以画出一下结构图。

结构图:
Java中23中设计模式(一)_第9张图片

项目类的目录如下:

Java中23中设计模式(一)_第10张图片

示例代码:

/**
 * 抽象组件
 * 火锅
 */
public interface HotPot {
    //锅底和菜品
    String desc();
    //价格
    double price();
}
/**
 * 被装饰者
 * 香辣火锅
 */
public class SpicyHotpot implements HotPot {
    @Override
    public String desc() {
        return "香辣火锅(¥15)";
    }

    @Override
    public double price() {
        return 15;
    }
}

/**
 * 被装饰者
 * 菌汤火锅
 */
public class MushroomHotpot implements HotPot {
    @Override
    public String desc() {
        return "菌汤火锅(¥18)";
    }

    @Override
    public double price() {
        return 18;
    }
}
/**
 * 装饰器
 * 1、抽象类(这个根据实际情况而定)
 * 1、实现抽象组件的接口
 * 2、拿到实现抽象组件的引用
 */
public abstract class HotPotDecorator implements HotPot {

    private HotPot hotPot;

    public HotPotDecorator(HotPot hotPot) {
        this.hotPot = hotPot;
    }

    @Override
    public String desc() {
        return hotPot.desc();
    }

    @Override
    public double price() {
        return hotPot.price();
    }
}
/**
 * 具体装饰类 继承 装饰者组件
 */
public class Beef extends HotPotDecorator {

    public Beef(HotPot hotPot) {
        super(hotPot);
    }

    @Override
    public String desc() {
        return super.desc()+"+牛肉(¥23)";
    }

    @Override
    public double price() {
        return super.price()+23;
    }
}

/**
 * 具体装饰类 继承 装饰者组件
 */
public class Mutton extends HotPotDecorator {

    public Mutton(HotPot hotPot) {
        super(hotPot);
    }

    @Override
    public String desc() {
        return super.desc()+"+羊肉(¥16)";
    }

    @Override
    public double price() {
        return super.price()+16;
    }
}

/**
 * 具体装饰类 继承 装饰者组件
 */
public class Potato extends HotPotDecorator {

    public Potato(HotPot hotPot) {
        super(hotPot);
    }

    @Override
    public String desc() {
        return super.desc()+"+土豆片(¥8)";
    }

    @Override
    public double price() {
        return super.price()+8;
    }
}
public class Main {

    public static void main(String[] args) {
        HotPot hp = new SpicyHotpot();

        System.out.println(hp.desc() + " ,价格是:" + hp.price());

        hp = new Beef(hp);
        System.out.println(hp.desc() + " ,价格是:" + hp.price());
        hp = new Mutton(hp);
        System.out.println(hp.desc() + " ,价格是:" + hp.price());
        hp = new Potato(hp);
        System.out.println(hp.desc() + " ,价格是:" + hp.price());

        System.out.println();
        System.out.println("=================分割线=======================");
        System.out.println();

        HotPot hp1 = new MushroomHotpot();
        System.out.println(hp1.desc() + " ,价格是:" + hp1.price());
        hp1 = new Beef(hp1);
        System.out.println(hp1.desc() + " ,价格是:" + hp1.price());
        hp1 = new Potato(hp1);
        System.out.println(hp1.desc() + " ,价格是:" + hp1.price());
    }

}

运行结果如下:

Java中23中设计模式(一)_第11张图片

8、责任链模式

定义:
  责任链:是为例避免请求发送者与多个请求处理这耦合在一起,将所有请求的处理者通过千亿对象记住下一对象的引用而连城一条链,当有请求发生时,可将请求沿着这条链传递,知道有对象处理它为止。

优点:

  1. 降低了对象之间的耦合度
  2. 增强了系统的可扩展性
  3. 增强了给对象指派职责的灵活性
  4. 简化了对象之间的连接
  5. 责任分担

缺点:

  1. 不能保证每一个请求一定被处理
  2. 当责任链较长时,会影响系统性能
  3. 增加了客户端的复杂性(比如客户端出错导致循环调用)

组成部分:

  1. 抽象处理者:定义一个抽象请求的接口,包含抽象处理方法和一个后继连接
  2. 具体处理者:实现抽象处理者的处理方法,判断是否处理本次请求,如果可以处理,则就自立处理,如果不可以处理,就转给下一个处理者。
  3. 客户类:创建处理链,并向链头的具体处理对象提交请求。

结构图:

Java中23中设计模式(一)_第12张图片
  原图地址:http://c.biancheng.net/uploads/allimg/181116/3-1Q116135Z11C.gif

例子1:请假条审批流程
  在公司,规定员工请假2天以内的,组长可以批准,5天以内的需要经理批准,10天以内的需要老板批准,然后10天以上的呢,需要辞职。这个就可以使用责任链来实现

项目目录如下:
Java中23中设计模式(一)_第13张图片

代码如下:

抽象处理类
//领导抽象类
public abstract class Leader {
    //下一个处理类的引用
    private Leader next;
    //处理方法
    abstract void handRequest(int days);

    public Leader getNext() {
        return next;
    }

    public void setNext(Leader next) {
        this.next = next;
    }
}
具体处理者
/**
 * 具体处理者
 * 组长,可以批两天以内的假
 */

public class GroupLeader extends Leader {

    @Override
    void handRequest(int days) {
        if (days <= 2) {
            System.out.println("组长批准了你的 " + days + " 天假。");
        } else {
            if (getNext() != null) {
                System.out.println("组长无权批准你的假,已提交给总经理审批");
                getNext().handRequest(days);
            } else {
                System.out.println("没有人处理你的申请");
            }
        }
    }
}

/**
 * 具体处理者
 * 经理,可以批5天以内的假
 */

public class Manager extends Leader {

    @Override
    void handRequest(int days) {
        if (days <= 5) {
            System.out.println("总经理批准了你的 " + days + " 天假。");
        } else {
            if (getNext() != null) {
                System.out.println("总经理无权批准你的假,已提交给老板审批");
                getNext().handRequest(days);
            } else {
                System.out.println("没有人处理你的申请");
            }
        }
    }
}

/**
 * 具体处理者
 * 老板,可以批10天以内的假
 */

public class Boss extends Leader {

    @Override
    void handRequest(int days) {
        if (days <= 10) {
            System.out.println("老板批准了你的 " + days + " 天假。");
        } else {
            System.out.println("请假天数太多,不予批准!可以考虑辞职");
        }
    }
}
客户端
public class Client {
    public static void main(String[] args) {
        //组长
        Leader groupleader = new GroupLeader();
        //经理
        Leader manager = new Manager();
        //老板
        Leader boss = new Boss();
        //组长的上级是经理
        groupleader.setNext(manager);
        //经理的上级是老板
        manager.setNext(boss);
        int day = 9;
        System.out.println("你请假的天数:"+day+ " 天。");
        groupleader.handRequest(day);

    }
}
运行结果

Java中23中设计模式(一)_第14张图片
Java中23中设计模式(一)_第15张图片Java中23中设计模式(一)_第16张图片

例子2:使用Filter模拟处理Request Response

  我们使用Filter来过滤前端页面传给服务器的数据,把带有Html标签的、敏感词汇的、URL地址的和笑脸的给修改了。并且还要实现 先执行完 request的过滤,然后在执行response的过滤 执行顺序如下图所示:

Java中23中设计模式(一)_第17张图片

项目目录如下:
Java中23中设计模式(一)_第18张图片

代码如下:

实体类
public class Request {

    private String reqStr;

    public String getReqStr() {
        return reqStr;
    }

    public void setReqStr(String reqStr) {
        this.reqStr = reqStr;
    }
}

public class Response {

    private String resStr;

    public String getResStr() {
        return resStr;
    }

    public void setResStr(String resStr) {
        this.resStr = resStr;
    }
}
抽象类
public interface Filter {
    public void doFilter(Request request, Response response, FilterChain fc);
}
FilterChain类
public class FilterChain implements Filter {

    private List<Filter> list = new ArrayList<>();
    //用来记录目前该执行的链条的位置
    int index = 0;

    public FilterChain add(Filter filter) {
        list.add(filter);
        return this;
    }

    @Override
    public void doFilter(Request request, Response response, FilterChain fc) {
        if (index == list.size()) return;
        Filter filter = list.get(index);
        //拿到filter以后,index加1,指向下一个filer
        index++;
        filter.doFilter(request, response, fc);
    }
}
具体抽象类
public class HtmlFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain fc) {

        String reqStr = request.getReqStr();
        request.setReqStr(reqStr + "---HTML");
        //当该处理类执行完request的filter以后,在外部调用链条的doFilter的方法
        //执行下一个处理类的request的filter
        fc.doFilter(request, response, fc);
        response.setResStr(response.getResStr() + "---HTML");

    }
}

public class SensitiveFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain fc) {
        String reqStr = request.getReqStr();
        request.setReqStr(reqStr + "---Sensi");
        fc.doFilter(request, response, fc);
        response.setResStr(response.getResStr() + "---Sensi");

    }
}
//其他的与之类似,我就不写了
运行结果

Java中23中设计模式(一)_第19张图片


参考文献

[1] 马士兵老师的视频
[2] Java设计模式:23种设计模式全面解析
[3] 责任链模式-模拟处理Reques Response

你可能感兴趣的:(java,java,设计模式)