从现在开始,假设我们是一家软件公司的职员,有个项目让我们做,有客户要我们创建一个名为SimUDuck的app(本文中一律用E文app代替中文“应用程序”)
SimUDuck是个有关鸭子的模拟程序,它可以显示各种不同种类的鸭子,模拟它们游泳,嘎嘎叫等行为。呵呵,很简单的吧。
我们当然要使用OO(本文中一律用E文OO代替中文“面向对象”)的技术和思想来实现这个程序。
所以呢,首先要创造Duck这个superclass(父类),所有种类的鸭子就可以从它继承了。这可是面向对象三态中最基本的一点哦。
Duck父类的代码基本上有以下方法组成:
Quack() ;//所有的鸭子都会叫,所以这些方法在父类中实现
Swim() ;//所有的鸭子都会游泳,所以这些方法在父类中实现
Display(); //因为不同的鸭子样子不同,所以要留到具体的子类去实现,把它先写出抽象类
继承Duck的子类,比如MallardDuck和RedheadDuck就要分别去具体实现display方法了,因为它们是不同种类的鸭子,所以display当然不同了。
代码的初步基本上写完了。利用了继承,貌似很完美。
可是~~~问题来了。
什么问题呢?就是,现在程序要添加一个功能:让鸭子飞起来。
客户是上帝嘛~在他们看来,让程序新增加一个功能应该不是难事吧。
恩,正常人的思维就是在父类里加上fly()方法,因为我们使用了继承这一OO技术,所以所有的鸭子都能继承到,很不错吧。
但是,程序出现bug了。
客户说,在他们的预想的程序中,有一种鸭子是RubberDuck(哦,我的天,橡胶小鸭),这种鸭子明显不能飞的嘛。
怎么办?利用继承的坏处显现出来了。它让所有的鸭子,不管活鸭死鸭都飞起来了。
/****************************************************************************/
思考下
/***************************************************************************/
解决的办法是有的。就是在RubberDuck这个子类中override(重写)一下fly()方法,让它不能飞。
可是这是一种治标不治本的方法,假如程序中还有别的像RubberDuck这样不能飞的鸭子,比如WoodDuck(木头小鸭),岂不是也要在这个子类中override一下fly()方法,一个类两个类override一下的话可以接受,一旦有成千上万个类要override的话,效率岂不是很低?
灵感闪现!看来继承是解决不了这个问题了,我们得另辟蹊径,interface怎么样?
我们可以把fly()实现成一个接口Flyable,让那些需要fly的鸭子去实现这个接口,而所有鸭子都需要的方法还是写在父类中。貌似不错的解决方法。
其实这么做的话很明显就是为了使用接口而去使用接口,因为在JAVA中,接口中是不实现任何方法的,所以这么做无疑是在浪费时间,还不如老老实实的在需要fly的类中,手动地添加fly方法呢。
现在我们要去思考的,是我们所遇到的问题究竟是什么?
在软件开发中,唯一不变的东西就是变化。无论你的程序在一开始写的多棒,功能有多完善,随着时间的流逝,程序一定会在使用中面临新的要求和变换以迎合客户的需求。
所以,不变则死!
我们要做的就是,do so with the least possible impact on the existing code that we could spend less time reworking code
以上便是软件设计的真谛。
下面是三条是很著名的设计原则:
1.Identify the aspects of your application that vary and separate them from what stays the same.
2.Program to an interface ,not an implementation.
3.Favor composition over inheritance.
简单的翻一下:
1.把程序中不变的部分和变化的部分隔离开来。
2.针对接口编程,而不是实现。
3.尽量多用组合,少用继承。
根据原则1,我们或许已经知道了解决Duck类中fly这个不合群方法的方法。
就是把它独立出去,单独形成一个类吧。
根据原则2,我们可以设计FlyBehavior这么一个接口,以及FlyWithWings和FlyNoWay这么两个类,以满足不同的需要。
最终的解决方案如下所示,它包含Duck抽象类,FlyBehavior接口,FlyWithWings和FlyNoWay这两个实现了接口的类,和最终的main方法:
abstract class Duck {
FlyBehavior flyBehavior;
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void swim() {
System.out.println("all duck swim");
}
}
interface FlyBehavior {
public void fly();
}
class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("i am flying");
}
}
class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("i can not fly");
}
}
class MallardDuck extends Duck {
public MallardDuck() {
flyBehavior = new FlyWithWings();
}
public void display() {
System.out.println("i am a real mallardduck!");
}
}
class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
}
public void display() {
System.out.println("i am a ModelDuck");
}
}
public class MiniDuckSimulator {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performFly();
Duck modelduck=new ModelDuck();
modelduck.performFly();
}
}
运行结果如下:
i am flying
i can not fly
仔细回味一下程序这么写的好处。比起一开始的设计,优点是什么?
从现在的设计中,我们可以发现,Duck类现在没有了fly()方法,而是把它委派给了FlyBehavior这一接口。
这就是今天最终要引出的主角:Strategy Pattern 策略模式
Gof对它的定义是:Ths strategy pattern defines a family of algorithms,encapsulates each one ,and makes them interchangeable.Strategy lets the algorithm vary independently from clients that use it.
先到此休息会。
分享到:
相关推荐
设计模式(22)-Strategy Pattern 设计模式(21)-Template Method Pattern 设计模式(20)-Visitor Pattern 设计模式(19)-Observer Pattern 设计模式(18)-Command Pattern 设计模式(17)-Chain of ...
1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以互换。策略模式让算法的变化独立于使用算法的客户端。在提供...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或时间点执行不同算法的情况。策略模式提供了一种灵活的方式来处理这种情况,通过将每种算法封装为一个...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件设计中,我们经常遇到需要在不同时间或根据不同条件使用不同算法的情况。策略模式允许我们将算法封装到独立的可互换的策略类中,从而使它们可以...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或场景来执行不同算法的情况。策略模式提供了一种将算法族封装到各自独立的类中,并在运行时选择具体...
策略模式是一种行为设计模式,它使得算法可以在运行时被更改。这种模式允许一个类的行为或其算法在运行时根据需要进行改变,通过这种方式,我们可以轻松地扩展不同的算法而不修改现有代码。 #### 主要问题 在软件...
【标题】"sprintboot-strategy-pattern-demo-master.zip" 是一个使用Spring Boot技术实现的策略模式示例项目,它提供了一种快速理解并应用策略模式的开箱即用的体验。 【描述】"基于springboot做了一个策略模式的...
"Design Pattern"这个压缩包文件很可能包含了一些关于设计模式的实例和文档,特别是提到了"design-pattern\doc\api"目录下的"index.html",这可能是一个交互式的文档或者教程,通过实例帮助开发者更好地理解设计模式...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或时间来改变算法的情况。策略模式提供了一种将算法封装到独立的对象中,使得它们可以互换使用的机制,...
在众多的设计模式中,策略模式(Strategy Pattern)是一种行为设计模式,它使你能在运行时改变对象的行为。在这个“JAVA设计模式例程-策略模式”的压缩包中,我们可以深入探讨策略模式的原理及其应用。 策略模式的...
Java设计模式是软件开发中的一种最佳实践,它总结了在解决特定问题时程序员们经常采用的有效方法。这个“JAVA设计模式-chm版”资源显然包含了关于Java设计模式的详细信息,便于理解和应用。设计模式是对常见问题的...
处理对象的多种状态及其相互转换——状态模式(五) 处理对象的多种状态及其相互转换——状态模式(六) 策略模式-Strategy Pattern 算法的封装与切换——策略模式(一) 算法的封装与切换——策略模式(二) 算法的...
在给定的文件中,提到了三种具体的设计模式:策略模式、简单工厂模式和工厂方法模式,以及一种抽象设计模式——抽象工厂模式。 1. **策略模式(Strategy Pattern)**: 策略模式定义了一系列的算法,并将每个算法...
这里我们关注的是一个名为"pattern.zip"的压缩包文件,它包含了23种经典的设计模式,这些模式在实践中被广泛使用,提高了代码的可读性、可维护性和可扩展性。这篇文章将详细探讨这些设计模式及其应用。 首先,23种...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或时间点执行不同算法的情况。策略模式提供了一种将算法族封装到各自独立的类中,并让它们之间可以互相...
在"Design Pattern - Strategy Design Pattern _ Model"这个主题中,可能包含了对策略模式的深入讲解和实例应用。文件"T23_设计模式_策略模式.ppt"可能是一个演示文稿,详细介绍了策略模式的原理、结构、优缺点以及...
- **策略**(Strategy):定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。 - **模板方法**(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。 - **访问者**(Visitor):...
- **策略模式(Strategy)**:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。 - **模板方法模式(Template Method)**:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。 - **观察者模式(Observer...
本资料包“DesignPattern - DesignPattern.zip”提供了对C++11中23种设计模式的全面讲解,特别是结合指针使用的部分,以下是对这些知识点的详细阐述: 1. **单例模式(Singleton)**:确保一个类只有一个实例,并...