Java常用设计模式

  使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理使用设计模式可以完美的解决很多问题,每种设计模式在现在中都有响应的原理来与之对应。在某些场景下,设计模式就是针对某类问题的某种通用方案。

一、设计模式简介

设计模式分为三个类别:

  • 创建型模式:对象实例化的模式,创建型模式用于解耦对象实例化的过程
  • 结构性模式:把类或对象结合在一起形成一个更大的结构
  • 行为型模式:类和对象如何交互,及划分责任和算法


创建型模式关键点:

  • 单例模式:某个类只能有一个实例,提供一个全局的访问点
  • 简单工厂:一个工厂类根据传入的参量决定创建出哪一种产品类的实例
  • 工厂方法:定义一个创建对象的接口,让子类决定实例化哪个类
  • 抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类
  • 建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造
  • 原型模式:通过复制现有的实例来创建新的实例

结构性模式关键点:

  • 适配器模式:将一个类的方法接口转换成客户希望的另外一个接口
  • 组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构
  • 装饰模式:动态的给对象添加新的功能
  • 代理模式:为其他对象提供一个代理以便控制这个对象的访问
  • 亨元模式:通过共享技术来有效的支持大量细粒度的对象
  • 外观模式:对外提供一个统一的方法,来访问子系统中的一群接口
  • 桥接模式:将对象部分和它的实现部分分离,使它们都可以独立的变化

行为性模式关键点:

  • 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现
  • 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器
  • 策略模式:定义一系列算法,把它们封装起来,并且使它们可以相互转换
  • 状态模式:允许一个对象在其对象内部状态改变时改变它的行为
  • 观察者模式:对象间的一对多的依赖关系
  • 备忘录模式:在不破坏封装的前提下,保持对象的内部状态
  • 中介者模式:用一个中介对象来封装一系列的对象交互
  • 命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化
  • 访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能
  • 责任链模式:将请求的发送者和接受者解耦,使得多个对象都有处理这个请求的机会
  • 迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构

二、常用设计模式

单例模式

单例模式三个特性:只有一个实例、自我实例化、提供全局访问点

当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。单例模式的主要优点就是节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。

/*
    单例模式之懒汉式
    线程不安全,延迟初始化,严格意义上不是单例模式
 */
public class LazyPattern {
    //自己创建一个对象
    public static LazyPattern lazy;
    //私有化构造器,放置被其他地方实例化
    private LazyPattern() {

    }
    //提供一个构造器给外部使用,存在一定的线程安全问题,线程A执行到new 的时候,线程B判断hungry=true,也进到new,这样就会创建两个实例
    public static LazyPattern getInstance(){
        if(lazy==null){
            lazy = new LazyPattern();
        }
        return lazy;
    }
}

懒汉式,就是实例在使用的时候才去创建,比较懒,用的时候检查有没有实例,如果没有实例,就自己新建一个。有线程安全和不安全两种写法,区别就是synchronized关键字

/*
    单例模式之饿汉式
    线程安全,比较常用,但容易产生垃圾,因为一开始就初始化
 */
public class HungryPattern {
    //定义的时候就把对象创建出来
    private static HungryPattern instance =  new HungryPattern();
    //私有构造器
    private HungryPattern(){

    }
    //外部调用构造器,一开始创建的时候就创建了对象,可以有效方式线程不安全问题
    public static HungryPattern getInstance(){
        return instance;
    }
}

饿汉式,就是比较勤,实例在初始化的时候就已经创建完毕,不管有没有使用到。好处是没有线程安全的问题,坏处是浪费内存空间

/*
    单例模式之双重锁模式
 */
public class HungrySyronPattern {
    private volatile static HungrySyronPattern instance;

    private HungrySyronPattern() {

    }

    public static HungrySyronPattern getInstance(){
            if(instance==null){
                synchronized (HungrySyronPattern.class){
                    if(instance==null){
                        instance = new HungrySyronPattern();
                    }
                }
            }
            return instance;
    }
}

双重锁模式,综合了饿汉和懒汉模式,在创建时增加了synchronized关键字,这样既保证了线程安全问题 ,也直接上锁提高了执行效率,节省 了内存空间

/*
    单例模式之静态类部类
    只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,
    只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。
 */
public class SinglePattern {

    private SinglePattern() {

    }

    public static SinglePattern getInstance(){
        return Inner.instance;
    }

    private static class Inner{
        private static  final SinglePattern instance = new SinglePattern();
    }
}

静态类部类,类似双重锁,实现起来更加简单

/*
    单例模式之枚举单例模式

 */
public enum EnumPattern {
    INSTANCE;

    public static EnumPattern getInstance(){
        return EnumPattern.INSTANCE;
    }
}

枚举,较为少见。

简单工厂模式

/*
    简单工厂模式
    定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
    结构:1、Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
    2、Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
    3、ConcreteProduct(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。
        它要实现抽象产品中声明的抽象方法(有关抽象类)
 */
public class SingleFactoryPattern {
    public static void main(String[] args) {
        Product product;
        product = Factory.GetProduct("A");//工厂类创建对象
        product.MethName();
        product.MethodDiff();
    }
}
abstract class Product{
    public void MethName(){
        //公共方法的实现
    }
    //生命业务抽象方法
    public abstract void MethodDiff();
}
class ProductA extends Product{

    @Override
    public void MethodDiff() {
        //业务方法的实现
    }
}

class ProductB extends Product{

    @Override
    public void MethodDiff() {
        //业务方法的实现
    }
}

class Factory{
    public static Product GetProduct(String arg){
        Product product =  null;
        if("A".equals(arg)){
            product = new ProductA();
        }else if("B".equals(arg)){
            product = new ProductB();
        }else{
            //其他情况
        }
        return product;
    }
}

抽象工厂模式

/*
    抽象工厂模式
    定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,
    属于对象创建型模式,是工厂方法模式的升级版,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是、
    一种非常好的解决方式。
    优缺点:1、隔离了具体类的生成,使得客户并不需要知道什么被创建,具有良好的封装性。
    2、横向扩展容易。同个产品族如果需要增加多个 产品,只需要增加新的工厂类和产品类即可。
    3、纵向扩展困难。如果增加新的产品组,抽象工厂类也要添加创建该产品组的对应方法,
        这样一来所有的具体工厂类都要做修改了,严重违背了开闭原则。
 */
public class AbstractFactoryPattern {
    public static void main(String[] args) {
        //定义出两个工厂
        AbstractCreator creator1 = new Creator1();
        AbstractCreator creator2 = new Creator2();
        //产生A1对象
        AbstractProductA a1 = creator1.createProductA();
        //产生A2对象
        AbstractProductA a2 = creator2.createProductA();
        //产生B1对象
        AbstractProductB b1 = creator1.createProductB();
        //产生B2对象
        AbstractProductB b2 = creator2.createProductB();
        a1.doSomething();
        a2.doSomething();
        b1.doSomething();
        b2.doSomething();
    }
}
//产品族的抽象类A
abstract class AbstractProductA {
    //每个产品共有的方法
    public void shareMethod() {
    }

    // 每个产品相同方法,不同实现
    public abstract void doSomething();
}
//产品族的抽象类B
abstract class AbstractProductB {
    //每个产品共有的方法
    public void shareMethod() {
    }

    // 每个产品相同方法,不同实现
    public abstract void doSomething();
}
//产品族的具体实现
class ProductA1 extends AbstractProductA {
    public void doSomething() {
        System.out.println("我是产品A1");
    }
}
//产品族的具体实现
class ProductA2 extends AbstractProductA {
    public void doSomething() {
        System.out.println("我是产品A2");
    }
}
//产品族的具体实现
class ProductB1 extends AbstractProductB {
    public void doSomething() {
        System.out.println("我是产品B1");
    }
}
//产品族的具体实现
class ProductB2 extends AbstractProductB {
    public void doSomething() {
        System.out.println("我是产品B2");
    }
}
//抽象工厂类AbstractCreator,有N个产品族,在抽象工厂类中就应该有N个创建方法。
abstract class AbstractCreator {
    //创建A产品
    public abstract AbstractProductA createProductA();

    //创建B产品
    public abstract AbstractProductB createProductB();
}
//创建产品的具体工厂,有N个产品等级就应该有N个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
class Creator1 extends AbstractCreator {
    public AbstractProductA createProductA() {
        return new ProductA1();
    }

    public AbstractProductB createProductB() {
        return new ProductB1();
    }
}
//创建产品的具体工厂,有N个产品等级就应该有N个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
class Creator2 extends AbstractCreator {
    public AbstractProductA createProductA() {
        return new ProductA2();
    }

    public AbstractProductB createProductB() {
        return new ProductB2();
    }
}

观察者模式

/*
    观察者模式
    定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
    简释:观察者一般可以看做是第三者,比如在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,
            这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了。
    成员:Subject:主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。
            抽象主题提供了一个接口,可以增加和删除观察者对象
          Observer:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
          ConcreteSubject:具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知
          ConcreteObserver:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同
     优缺点:观察者和被观察者是抽象耦合的,建立了一套触发机制
     如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
     如果观察者和观察目标间有循环依赖,可能导致系统崩溃
     没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的
 */
public class Client {
    public static void main(String[] args) {
        //创建一个主题
        ConcreteSubject subject = new ConcreteSubject();
        //定义一个观察者
        Observer observer = new ConcreteObserver();
        //观察
        subject.addObserver(observer);
        //开始活动
        subject.doSomething();
    }
}
//首先定义一个观察者数组,并实现增、删及通知操作。它的职责很简单,就是定义谁能观察,谁不能观察,
// 用Vector是线程同步的,比较安全,也可以使用ArrayList,是线程异步的,但不安全。
class Subject{
    //观察者数组
    private Vector<Observer> oVector = new Vector<>();

    //增加一个观察者
    public void addObserver(Observer observer) {
        this.oVector.add(observer);
    }

    //删除一个观察者
    public void deleteObserver(Observer observer) {
        this.oVector.remove(observer);
    }

    //通知所有观察者
    public void notifyObserver() {
        for(Observer observer : this.oVector) {
            observer.update();
        }
    }
}
//具体主题
class ConcreteSubject extends Subject{
    //具体业务
    public void doSomething() {
        //
        super.notifyObserver();
    }
}
//抽象观察者Observer
interface Observer {
    public void update();
}
//具体观察者
class ConcreteObserver implements Observer {

    @Override
    public void update() {
        System.out.println("收到消息,进行处理");
    }
}
原文地址:https://www.cnblogs.com/yfstudy/p/13517898.html