Java常用设计模式总结

本文是对鸿洋大神的Java设计模式系列博客的总结,涵盖了23种设计模式,包括观察者模式、工厂模式、单例模式、策略模式等。通过具体的代码示例,详细介绍了每种模式的原理和应用场景,旨在帮助读者深入理解并掌握Java设计模式。
摘要由CSDN通过智能技术生成

前言:鸿洋大神的设计模式系列博客已经阅读完毕,下面来做个总结。


Java 设计模式(观察者模式、工厂模式、单例模式、策略模式、命令模式、装饰者模式、外观模式、模板方法模式、状态模式)

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

设计模式分为三种类型,共23种:


        

Pattern Analysis

1. 观察者模式

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

  • 对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。
  • 专题接口:Subject.java ;

·          /**

·           *注册一个观察者

·           */

·          publicvoidregisterObserver(Observer observer);

·         

·          /**

·           *移除一个观察者

·           */

·          publicvoidremoveObserver(Observer observer);

·         

·          /**

·           *通知所有观察者

·           */

 publicvoidnotifyObservers();

·         @Override

·        publicvoidregisterObserver(Observer observer) {

·            observers.add(observer);

·        }

·        @Override

·        publicvoidremoveObserver(Observer observer) {

·            int index= observers.indexOf(observer);

·            if (index>=0) {

·                observers.remove(index);

·            }

·        }

·        @Override

·        publicvoidnotifyObservers() {

·            for (Observerobserver: observers) {

·                observer.update(msg);

·            }

·        }

·        /**

·         *主题更新信息

·         */

·        publicvoid setMsg(Stringmsg) {

·            this.msg= msg;

·            notifyObservers();

}

·        publicObserverUser1(Subject subject) {

·              subject.registerObserver(this);

·          }

·          @Override

·          publicvoid update(Stringmsg) {

·              Log.e("-----ObserverUser1","得到 3D号码:"+ msg+",我要记下来。 ");

  }

·        //创建服务号

·        objectFor3D=new ObjectFor3D();

·        //创建两个订阅者

·        observerUser1=newObserverUser1(objectFor3D);

·        observerUser2=newObserverUser2(objectFor3D);

·        //两个观察者,发送两条信息

·        objectFor3D.setMsg("2016101213D号为:127");

objectFor3D.setMsg("201610223D号为:000");

2. 工厂模式

简单列一下这个模式的家族:

  • 1、静态工厂模式
    • 这个最常见了,项目中的辅助类,TextUtil.isEmpty等,类+静态方法。
  • 2、简单工厂模式(店里买肉夹馍)
    • 定义:通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
    • 根据类型直接创建肉夹馍:SimpleRoujiaMoFactory.java

·        public RoujiaMocreatRoujiaMo(String type) {

·            RoujiaMo roujiaMo=null;

·            switch (type) {

·                case"Suan":

·                    roujiaMo=newZSuanRoujiaMo();

·                    break;

·                case"La":

·                    roujiaMo=new ZLaRoujiaMo();

·                    break;

·                case"Tian":

·                    roujiaMo=new ZTianRoujiaMo();

·                    break;

·                default://默认为酸肉夹馍

·                    roujiaMo=newZSuanRoujiaMo();

·                    break;

·            }

·            return roujiaMo;

}

  • 3、工厂方法模式(开分店)
    • 定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
    • 对比定义:
      • 1、定义了创建对象的一个接口:public abstract RouJiaMo sellRoujiaMo(String type);
      • 2、由子类决定实例化的类,可以看到我们的馍是子类生成的。
    • 提供创建肉夹馍店抽象方法:RoujiaMoStore.java

publicabstract RoujiaMo sellRoujiaMo(String type);

  • 4、抽象工厂模式(使用官方提供的原料)
    • 定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
    • 对比定义:
      • 1、提供一个接口:public interface RouJiaMoYLFactroy
      • 2、用于创建相关的或依赖对象的家族 public Meat createMeat();public YuanLiao createYuanliao();我们接口用于创建一系列的原材料。
    • 创建用于提供原料的接口工厂:RoujiaMoYLFactory.java
    • 各自分店实现接口,完成原料提供:XianRoujiaMoYLFoctory.java
    • 准备时,使用官方的原料:RoujiaMo.java

o   /**

o   *准备工作

o   */

o   publicvoidprepare(RoujiaMoYLFactory roujiaMoYLFactory) {

o       Meet meet=roujiaMoYLFactory.creatMeet();

o       YuanLiao yuanLiao=roujiaMoYLFactory.creatYuanLiao();

o       Log.e("---RoujiaMo:","使用官方的原料 ---"+ name+":揉面-剁肉-完成准备工作 yuanLiao:"+meet+"yuanLiao:"+yuanLiao);

}

3. 单例设计模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

  • 定义:只需要三步就可以保证对象的唯一性
    • (1) 不允许其他程序用new对象
    • (2) 在该类中创建对象
    • (3) 对外提供一个可以让其他程序获取该对象的方法
  • 对比定义:
    • (1) 私有化该类的构造函数
    • (2) 通过new在本类中创建一个本类对象
    • (3) 定义一个公有的方法,将在该类中所创建的对象返回

·        private SingletonLanHan(){}

·        privatestatic SingletonLanHansingletonLanHanFour;

·        publicstatic SingletonLanHangetSingletonLanHanFour() {

·              if(singletonLanHanFour==null) {

·                  synchronized(SingletonLanHan.class) {

·                      if(singletonLanHanFour==null) {

·                          singletonLanHanFour=newSingletonLanHan();

·                      }

·                  }

·              }

·              returnsingletonLanHanFour;

·        }

4. 策略模式

策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。

  • 以创建游戏角色为例子:
    • 最初的游戏角色的父类:Role.java
    • 发现有重复代码后,重构后的父类:Role.java
  • 总结:
    • 1、封装变化(把可能变化的代码封装起来)
    • 2、多用组合,少用继承(我们使用组合的方式,为客户设置了算法)
    • 3、针对接口编程,不针对实现(对于Role类的设计完全的针对角色,和技能的实现没有关系)
  • 最后测试:创建角色:

·        RoleA roleA=new RoleA("---A");

·        roleA.setiDisplayBehavior(new DisplayYZ())

·             .setiAttackBehavior(new AttackXL())

·             .setiDefendBehavior(new DefendTMS())

·             .setiRunBehavior(new RunJCTQ());

·        roleA.display();//样子

·        roleA.attack();//攻击

·        roleA.run();//逃跑

roleA.defend();//防御

5. 适配器模式

定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。

  • 以充电器为实例: 手机充电器一般都是5V左右吧,咱天朝的家用交流电压220V,所以手机充电需要一个适配器(降压器)
  • 一部手机: Mobile.java
  • 手机依赖一个提供5V电压的接口: V5Power.java
  • 我们拥有的是220V家用交流电: V220Power.java
  • 适配器,完成220V转5V的作用V5PowerAdapter.java
  • 最后测试:给手机冲个电:

·        Mobile mobile=new Mobile();

·        V5Power v5Power=new V5PowerAdapter(new V200Power());

mobile.inputPower(v5Power);

6. 命令模式

定义:将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化:将请求封装成对象,将动作请求者和动作执行者解耦。)

  • 需求:最近智能家电很火热,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
  • 1、家电的API:Door.java
  • 2、把命令封装成类:
  • 3、遥控器:ControlPanel.java
  • 4、定义一个命令,可以干一系列的事情:QuickCommand.java

·        QuickCommand quickCloseCommand=new QuickCommand(new Command[]{newLightOffCommand(light),newComputerOffCommand(computer),new DoorCloseCommand(door)});

·        controlPanel.setCommands(6,quickOpenCommand);

controlPanel.keyPressed(6);

·        controlPanel.setCommands(0,newDoorOpenCommand(door));//开门

controlPanel.keyPressed(0);

7. 装饰者模式

装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

  • 先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。
  • 需求:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:
  • 1、装备的超类:IEquip.java
  • 2、各个装备的实现类:
  • 3、装饰品的超类(装饰品也属于装备):IEquipDecorator.java
  • 4、装饰品的实现类:
  • 5、最后测试:计算攻击力和查看描述:

·        Log.e("---","一个镶嵌2颗红宝石,1颗蓝宝石的靴子: ");

·        IEquip iEquip=newRedGemDecotator(new RedGemDecotator(newBlueGemDecotator(new ShoeEquip())));

·        Log.e("---","攻击力:"+ iEquip.caculateAttack());

Log.e("---","描述语:"+ iEquip.description());

8. 外观模式

定义:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。

  • 需求:我比较喜欢看电影,于是买了投影仪、电脑、音响、设计了房间的灯光、买了爆米花机,然后我想看电影的时候,我需要一键观影和一键关闭。
  • 每个设备类的开关等操作:
  • 电影院类:HomeTheaterFacade.java

·        /**

·         *一键观影

·         */

·        publicvoid watchMovie() {

·            computer.on();

·            light.down();

·            popcornPopper.on();

·            popcornPopper.makePopcorn();

·            projector.on();

·            projector.open();

·            player.on();

·            player.make3DListener();

}

    • 最后测试:一键观影:

new HomeTheaterFacade(computer, light, player, popcornPopper, projector).watchMovie();

9. 模板方法模式

定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

  • 需求:简单描述一下:本公司有程序猿、测试、HR、项目经理等人,下面使用模版方法模式,记录下所有人员的上班情况
  • 模板方法模式中的三类角色
    • 1、具体方法(Concrete Method)
    • 2、抽象方法(Abstract Method)
    • 3、钩子方法(Hook Method)
  • 工人的超类:Worker.java

·        //具体方法

·        publicfinalvoid workOneDay() {

·            Log.e("workOneDay","-----------------workstart----------------");

·            enterCompany();

·            work();

·            exitCompany();

·            Log.e("workOneDay","-----------------workend----------------");

·        }

·        //工作 抽象方法

·        publicabstractvoid work();

·        //钩子方法

·        publicbooleanisNeedPrintDate() {

·            returnfalse;

·        }

·        privatevoid exitCompany() {

·            if(isNeedPrintDate()) {

·                Log.e("exitCompany","---"+new Date().toLocaleString()+"--->");

·            }

·            Log.e("exitCompany", name +"---离开公司");

}

·        /**

·         *重写父类的此方法,使可以查看离开公司时间

·         */

·        @Override

·        publicbooleanisNeedPrintDate() {

·            returntrue;

}

  • 最后测试:
    • 查看所有人员的工作情况:

o   QAWorkerqaWorker=new QAWorker("测试人员");

o   qaWorker();

o   HRWorkerhrWorker=new HRWorker("莉莉姐");

o   hrWorker.workOneDay();

...

    • 查看程序猿离开公司的时间:

o   ITWorkeritWorker=new ITWorker("jingbin");

itWorker.workOneDay();

10. 状态模式

定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

  • 定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。
  • 需求:已自动售货机为例(有已投币、未投币等状态和投币、投币等方法)
  • 最初实现待改进的售货机:VendingMachine.java
  • 改进后的售货机(更具有延展性):VendingMachineBetter.java

·        //放钱

·        publicvoid insertMoney() {

·            currentState.insertMoney();

·        }

·        //退钱

·        publicvoid backMoney() {

·            currentState.backMoney();

·        }

·        //转动曲柄

·        publicvoid turnCrank() {

·            currentState.turnCrank();

·            if (currentState== soldState|| currentState== winnerState) {

·                currentState.dispense();//两种情况会出货

·            }

·        }

·        //出商品

·        publicvoid dispense() {

·            Log.e("VendingMachineBetter","---发出一件商品");

·            if (count>0) {

·                count--;

·            }

·        }

·        //设置对应状态

·        publicvoid setState(Statestate) {

·            this.currentState= state;

}

  • 改进后的售货机测试:

·        //初始化售货机,且里面有3个商品

·        VendingMachineBetter machineBetter=newVendingMachineBetter(3);

·        machineBetter.insertMoney();

machineBetter.turnCrank();

Download

    Thanks

     源码地址链接:https://github.com/371894545/Pattern#pattern



    • 1
      点赞
    • 10
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    java设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 设计模式遵循的原则有6个: 1、开闭原则(Open Close Principle)   对扩展开放,对修改关闭。 2、里氏代换原则(Liskov Substitution Principle)   只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。 3、依赖倒转原则(Dependence Inversion Principle)   这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。 4、接口隔离原则(Interface Segregation Principle)   使用多个隔离的借口来降低耦合度。 5、迪米特法则(最少知道原则)(Demeter Principle)   一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。 6、合成复用原则(Composite Reuse Principle)   原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值