zoukankan      html  css  js  c++  java
  • 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("收到消息,进行处理");
        }
    }
  • 相关阅读:
    Oracle 数据库对象
    oracle基础知识
    中文乱码问题
    会话技术Cookie&Session
    HttpServletRequest请求
    JAVA基础之设置随机成语验证码
    HttpServletResponse响应
    Spring注解 AOP@Aspect
    Visual studio Code使用技巧
    缓存相关
  • 原文地址:https://www.cnblogs.com/yfstudy/p/13517898.html
Copyright © 2011-2022 走看看