首页 > 设计模式

模板方法模式是编程中经常用到到的模式。它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现。这样,新的子类可以在不改变一个算法结构的前提下重新定义该算法的某些特定步骤。

核心:处理某个流程的代码已经都具备,但是其中某个节点的代码暂时不能确定。因此,可以将该节点的代码实现转移给子类完成。即:处理步骤父类定义好,具体实现延迟到子类中定义,由父类进行整个过程的控制。

 

使用场景:实现一个算法时,整体步骤很固定,但是某些部分易变。易变部分可以抽象出来,供子类实现。

 

比如一个场景:

玩氪金手游充钱抽卡的流程。可以确定的是

第一步:打开氪金界面。

第二步:选择氪金。

第三步:选择支付方式。

最后:抽奖。

 

假设其他流程均为固定,而其中只有选择支付方式这一点可能会有所变化。比如可以用支付宝、微信等等支付。

那么要实现这种需求,每种方式都重复进行一遍编写的话代码太多,过于丑陋。

这时即可使用模板方法模式,将其固定的流程定死,并将选择支付方式声明为抽象,强制子类实现。

 

代码实现:

氪金的模板方法,可以看见我实现了除【选择支付方式】以外其余所有的方法。并且将流程控制在内部。

子类的权限只够修改除了执行整个氪金流程以外的方法。并且需要强制实现选择支付方式的方法。

 

实现其抽象方法的具体类以及客户端调用者:

若实现模板方法的子类并不复杂的话可考虑将其写成匿名内部类。若算法特别复杂并且需要实现的抽象的方法不止一个,那还是老老实实写个子类继承比较好。


System.out:

进入充值界面…
氪金!
用支付婊付钱
抽奖,哇又是保底SR

进入充值界面…
氪金!
用 weChat 付钱
抽奖,哇又是保底SR

进入充值界面…
氪金!
用 PY 付钱
抽到SSR辣!


 

我写的代码只是最简单的,进行举例用。模板方法模式在生产中应用有可能不止一个 abstract method。

甚至子类不止要重写抽象方法,非抽象的方法也有可能选择性重写。

但是,就算其每个节点变化多端,只要执行流程还是固定的,使用该模式肯定能让编码效率、维护效率、扩展效率更上一层楼。

 

 

阅读全文

策略模式是一种对象行为型模式。一般对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一个问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法。

本质:      分离算法,选择实现

 

–以下摘自 http://www.runoob.com

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

–摘要结束

 

下面是我写的策略模式的场景应用,场景为用户氪金。根据用户不同,需要采取的算法不同。

如果是普通的实现,即if..else实现 :

该种实现应该是一般人第一时间思考到的方式吧。

但是在业务巨复杂算法各种诡异的实际生产场景中,这种类似的需求要是用if..else实现的话,那画面真是太美妙了。

 

这个时候用策略模式重构一下。

策略接口:

 

具体的几个策略类:

 

重点,管理策略的上下文对象,一般调用者会根据该对象来执行不同的策略,而执行不同的算法。

 

跟上边简单实现的的if..else不同,调用者使用策略模式的方法:

执行后输出语句为:

白嫖用户充钱得10倍钻
您充钱648元,共获得:6480钻,下次再来氪哦

高贵的黄金会员充钱得13倍钻
您充钱648元,共获得:8424钻,下次再来氪哦

 

成功执行了不同的策略~ 并且代码优雅,可拓展性较强,可以说是很灵性了。

 

另外:

关于策略模式(strategy)与工厂模式(factory),两者确实比较相似,以至于我刚接触时感到很疑惑,在经过一番资料的查找后终于渐渐明了…其实还真差不多。你用其中一个能完成的功能用另一个也能完成的有模有样的。两者合二为一,那更是牛B,可以在Context上下文对象中使用factory来实例化strategy对象。这样调用者只需要和一个类进行交互即可实现选择不同策略的功能。

分类举例的话:

  • 工厂模式是对象创建型模式,专门用于创建对象的,他根据需求创建出不同的实例,将对象的创建和调用者进行了解耦,解决了资源的统一分发。
  • 策略模式是对象行为型模式,作用是让一个对象在许多行为中选择一种行为执行,他将策略的变化和使用策略的对象进行了解耦

 

简单来说工厂模式封装对象,实例化对象后调用的时候要知道具体的方法,策略模式封闭的是行为,调用的时候必须先制定实例化具体的类,再调用抽象的方法。

 

 

阅读全文

工厂模式

 

工厂模式主要是实现了创建和调用者的分离

 

核心本质:

  • 实例化对象,用工厂方法代替new操作
  • 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦

 

工厂模式(factory)大概分为三种:

  • 简单工厂模式:
    • 用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码)
  • 工厂方法模式
    • 用来生产同一等级结构中的固定产品(支持增加任意产品)
  • 抽象工厂模式
    • 用来生产不用产品族的全部产品(对于增加新的产品无能为力;支持增加产品族)

 

简单工厂

  • 简单工厂也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接收的参数不同来返回不同的对象实例
  • 缺点是对于增加新产品无能为力,不修改代码就不能扩展,必须修改已有的代码。

例如:

有这么几个东西,一个Car接口,还有实现了Car接口的宝马和奥迪类

 

此时,传统的new操作是这样的

 

这样,我这个TestCar需要知道:Car类、Audi类、BMW类

那以后要是这Car有一百个实现类呢= =这个时候,我要是想要new一个Car的实现类出来,但又不想要和这一堆复杂的构造逻辑耦合,怎么办?使用工厂模式嘛

工厂类最大好处让是使用者和对象的创建分离。使用者再也不担心,对象是怎么创建的。用上接口,使用者更不需要知道对象是谁。

我只要这样创建出一个工厂类(我这用的是IF…ELSE,用switch啥的都行):

 

这一切就解决了

创建Car实现类的时候只需要这样:

 

这里与我调用者有关系的只有Car接口、CarFacory工厂类、以后就是有一万个不同的实现类也和我调用者没半毛钱关系

这样就隐藏了实现类的细节,调用者也不需要知道这个对象是咋创建的

你需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。

我就一买家,只要这车开的动就行了。我还自个造个车子?

 

这就是简单工厂了。也是用的最多的工厂

 

工厂方法模式

  • 为了避免简单工厂模式的缺点、不完全满足OCP
  • 工厂方法模式和简单工厂模式最大的不同在于,简单工程模式只有一个工厂类(对于一个项目或一个独立模块而言),而工厂方法模式有一组实现了相同接口的工厂类

工厂类大概这样:

 

在这个抽象的工厂类基础上,可以添加无数个具体的创建某个产品的实现类

比如:

 

创建对象的话就这样:

 

在设计模式上来说最好选择用工厂方法模式,虽说工厂方法模式便于添加产品,但是实际上一般都用简单工厂,因为工厂方法模式的类肯定会挺多的,难的管理。

 

 

阅读全文

单例模式

核心作用:

  • 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

 

常见的几种单例模式实现方式

  • 饿汉式(线程安全,调用效率高。但是不能延时加载。)
  • 懒汉式(线程安全,调用效率不高。但是可以延时加载)
  • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题。不建议使用)
  • 静态内部类式(线程安全,调用效率高,可以延时加载)
  • 枚举单例(线程安全,调用效率高。不能延时加载)

 

 

饿汉式实现:

 

饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题,因此可以省略synchronize关键字。

问题:如果只是加载该类,而不是要调用getInstance()方法,甚至永远没有调用,则会造成资源浪费。

 

懒汉式实现:

 

 

延时加载!懒加载,真正用的时候才加载

问题:资源利用效率高了。但是,每次调用getInstance()方法时都要同步,并发效率较低

 

 

 

静态内部类式(也是一种懒加载方式):

 

要点:

  • 外部类没有static属性,则不会像饿汉式那样立即加载对象。
  • 只有真正调用getInstance(),才会加载静态内部类。加载类是是线程安全的。Instance是static final类型,保证了内存中只有一个实例存在且只能被赋值一次,从而保证了线程安全性
  • 兼备了并发高效调用和延迟加载的优势!

 

枚举式:

 

 

Double-Check双重锁定式,这种方式有问题,但是我看百度上说JDK1.5之后添加了一个关键字:volatile,这个可以解决双重锁定式的问题。自个研究吧

还是写一下

 

阅读全文
EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00