在说策略模式之前,我们先来分析一个需求。
一、需求分析及实现过程
某商场经常有促销活动,第一次是满200送80,第二次是所有商品打8折,第三次是所有商品打9折,第四次是满300送120等等。如果让你设计你怎么做?
我们都在说面向对象编程,但是并不是类越多越好。分类的目的是为了抽象,将所有共性(相同的属性和功能)的对象抽象成一个类。
我们先来找共性,打折类的需求我们可以抽象成一个需求,因为他们的共性就是折扣率和原价。
满多少送多少类可以抽象成一个需求,因为他们的共性就是总价和扣除价。
正常价是原价。
从需求中我们可以看到,我们现在有三类需求,这三类需求分别抽象成三个共性类:正常价格类,折扣类,满多少送多少类。
我们想一下,这三个类有什么相同点?就是不管是哪个类,既然是卖商品,最后都要算总价,因此,我们可以定义一个父类cashSuper,提供统一方法接口cashTotal。因此,我们抽象出的结构类图如下:
我们按照上述类图,来定义各类:
父类CashSuper,提供总价接口。
public interface CashSuper { double cashTotal(double total); }
正常价类,实现父类接口,总价计算方式为商品原总价。
public class CashNomal implements CashSuper { public double cashTotal(double total) { return total; } }
折扣类,实现父类接口,总价计算方式为 折扣*商品原总价:
public class CashDiscount implements CashSuper { private double discount; public CashDiscount(String discount){ this.discount = Double.parseDouble(discount); } public double cashTotal(double total) { //最后的商品总价是 原总价*折扣 return total*discount; } }
返利类,实现父类接口,总价计算方式为 商品原总价-根据返利条件算出的返利金额:
public class CashReturn implements CashSuper { //返利条件 private double returnCondition; //返利金额 private double returnMoney; //对于消费满多少送多少的,我们需要知道返利的条件(比如满300),我们还需要满足条件后赠费的金额 public CashReturn(String returnCondition,String returnMoney){ this.returnCondition = Double.parseDouble(returnCondition); this.returnMoney = Double.parseDouble(returnMoney); } public double cashTotal(double total) { //最后的商品总价是 总价减去返利价 if(total>this.returnCondition){ total = total - Math.floor(total/returnCondition)*returnMoney; return total; } return total; } }
好了,根据UML类图我们建立了基本的类,并且都实现了CashSuper中的总价计算方法。这么多类,每个类的的总价计算方法不尽相同,我们下一步怎么做?
我们看看类图,CashSuper是所有实现的父接口类,让一个对象持有这个接口类的实现对象,我们是不是可以不需要关注具体实现呢?我们尝试下。先修改类图。
定义一个CashContext类,它持有CashSuper类,在获取总价时,让他负责去找对应的实现,我们不关心实现内容,具体如下:
public class CashContext{ //持有各种促销手段的父类对象 private CashSuper cs; //根据具体的促销策略,我们初始化父类实现 public CashContext(CashSuper cs){ this.cs = cs; } //直接将原总价传递,让具体的实现去处理得到最后的总价 public double getTotal(double total) { return cs.cashTotal(total); } }
但是这么做,客户端就需要承担初始化CashContext的任务,如下:
public static void main(String[] args){ int strategyType = 1; double oldTotal = 888; CashContext cc = null; //1.代表正常收费 2.代表打八折 3.代表满300送100 switch (strategyType){ case 1: cc = new CashContext(new CashNomal()); break; case 2: cc = new CashContext(new CashDiscount("0.8")); break; case 3: cc = new CashContext(new CashReturn("300","100")); break; } System.out.println("最后的总价是:"+cc.getTotal(oldTotal)); }
那么有没有更好的方式,将这些判断逻辑转移,而使客户端对外统一?我们看到,上面的判断代码主要是为了获取不同的CashSuper,那么我们就可以把生产CashSuper过程使用简单工厂模式去做。我们先修改CashContext类,让它自己去根据类型去获取CashSuper,代码如下:
public class CashContext{ //持有各种促销手段的父类对象 private CashSuper cs; //根据具体的促销策略,我们初始化父类实现 public CashContext(int strategyType){ //1.代表正常收费 2.代表打八折 3.代表满300送100 switch (strategyType){ case 1: cs = new CashNomal(); break; case 2: cs = new CashDiscount("0.8"); break; case 3: cs = new CashReturn("300","100"); break; } this.cs = cs; } //直接将原总价传递,让具体的实现去处理得到最后的总价 public double getTotal(double total) { return cs.cashTotal(total); } }
这样,我们的客户端代码就很简单了,只需要传入促销策略类型,其他的事情就不需要管了:
public static void main(String[] args){ //1.代表正常收费 2.代表打八折 3.代表满300送100 int strategyType = 3; double oldTotal = 888; CashContext cc = new CashContext(strategyType); System.out.println("最后的总价是:"+cc.getTotal(oldTotal)); }
二、总结
我们回过头来,什么是策略模式。策略模式定义了一组算法,分别封装起来,让它们之间可以互相替换,而算法的变化不会影响客户的使用。每一种算法的要完成的工作是相同的,只是实现不同,因此我们可以抽象出公共的算法接口类Strategy。那么为什么要增加Context类?为了功能层次清晰,因为Context类拥有了Strategy类的实现对象,只要提供了策略类Strategy的具体实现对象,Context类就可以统一对外提供客户端想要的结果。这样,外部看起来是透明统一的。这样,后期维护时候,不需要修改客户端代码,只需要修改统一对外的Context类。也就是说,策略模式对外的统一对象就是Context。
我们看下策略模式的结构类图:
当然,让Context类中承担判断也是让人很不爽的,一堆判断,后期增加促销类型时,虽然客户端不用管,但是也得修改这里,所以,我们在说到反射时,再优化这里的代码。
相关推荐
Java设计模式是软件开发中的一种最佳实践,它总结了在解决特定问题时程序员们经常采用的有效方法。这个“JAVA设计模式-chm版”资源显然包含了关于Java设计模式的详细信息,便于理解和应用。设计模式是对常见问题的...
Java设计模式详解合集是一份宝贵的资源,包含了丰富的面向对象设计原则和多种设计模式的深入讲解。这份资料旨在帮助开发者提升软件设计能力,遵循良好的编程实践,提高代码的可读性、可维护性和复用性。以下是其中...
在Java编程中,有23种经典的GoF(Gang of Four)设计模式,它们被分为三大类:创建型、结构型和行为型。本资源集合了这些模式的详细解释与源码分析,旨在帮助开发者深入理解和应用设计模式。 1. 创建型模式...
Java中的23种设计模式是软件工程中非常重要的概念,它们是解决常见编程问题的成熟解决方案,被广泛应用于各种复杂的软件系统中。这些模式在不同的上下文中提供了可重用的结构和行为,使得代码更加清晰、可维护和扩展...
Java设计模式是一种在特定场景下解决软件设计问题的方法论。设计模式能够帮助开发者在面对复杂问题时,更有效地组织代码、提高程序的可维护性和可扩展性。根据不同的应用场景,设计模式被分为三大类:创建型模式、...
内容包括统一建模语言基础知识、面向对象设计原则、设计模式概述、简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式、适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、...
### Java设计模式的应用 #### 一、引言 在当今快速发展的软件开发领域,Java作为一门功能强大且灵活的语言,不仅拥有丰富的API资源,还能与强大的数据库系统无缝对接。这使得许多开发人员能够以模块化的形式构建...
" JAVA 设计模式概述" JAVA 设计模式是指在软件设计过程中,为了提高代码的可维护性、灵活性和可扩展性所使用的一些惯用解决方案。JAVA 设计模式可以分为三种:创建模式、结构模式和行为模式。 1. 创建模式 创建...
在Java中,"JAVA设计模式.mobi"这本书可能涵盖了如下设计模式的详细讲解: 1. 单例模式:保证一个类只有一个实例,并提供全局访问点。在Java中,有多种实现单例的方式,包括饿汉式、懒汉式、双重检查锁定(Double-...
Java设计模式是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。 设计模式的六大原则 1. 开闭原则...
设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板或蓝图。...在"java24种设计模式详解"这个资源中,你会找到每种模式的详细讲解和实例,这将有助于你深入理解并掌握它们。
Java 中 23 种设计模式详解 在软件设计中,设计模式是解决特定问题的通用解决方案。 Java 中有 23 种常见的设计模式,下面将对每种设计模式进行详细的解释: 1. 抽象工厂模式(Abstract Factory) 抽象工厂模式...
《Java设计模式实战详解》 在Java编程领域,设计模式是一种通用、可重用的解决方案,用于解决在软件设计中常见的问题。这个压缩包“java-design-patterns-master”显然是一个专注于Java设计模式的学习资源,旨在...
Java 策略模式详解 策略模式是一种行为型设计模式,它允许您定义一系列算法,将每个算法封装起来,并使它们可以互换使用。这种模式使得算法可以独立于使用它们的客户端而变化。在 Java 中,策略模式通常由一个接口...
Java设计模式中的策略模式是一种行为设计模式,它允许在运行时选择不同的算法或策略,以适应不同的业务需求。策略模式的核心思想是将算法封装到独立的类中,这些类遵循一个公共接口,使得它们可以相互替换。这样做的...
以下是对标题"Java设计模式相关书籍"及描述"设计模式之禅 深入浅出"中所包含的关键知识点的详细阐述。 1. **设计模式的分类** 设计模式通常分为三大类:创建型模式(Creational Patterns)、结构型模式...
在Java编程中,有23种经典的设计模式,它们是面向对象设计的核心部分,帮助我们编写可维护、可扩展且高效的应用程序。以下是这23种设计模式的概述,结合代码实例进行详细说明。 1. **单例模式(Singleton)**:确保...
### 后端-设计模式-java-精讲 #### 一、设计模式概述 设计模式是在软件工程领域中,为了应对特定的问题或需求而形成的最佳实践的解决方案。它们为解决常见问题提供了一种标准的方法,有助于提高代码的复用性、...
### Java设计模式选择题复习知识点详解 #### 工厂系列模式的优缺点 - **优点**: - **解耦**:工厂模式的核心优势之一在于它让用户代码与具体产品的实现相分离,使得用户无需了解产品是如何创建的,只需要知道...