摘要:不会叫鸭子呱呱呱叫。。。。。。此时我刚刚写的例子基于一个策略模式思想写的。感谢你看到这里,策略模式部分结束,本人文笔随便,若有不足或错误之处望给予指点,度弯腰很快我会发布下一个设计模式内容,生命不息,编程不止参考书籍设计模式
并不是每个自称自己是个OO的人,他就一定能运用好OOP。
普通程序员写的东西好比一把普通钥匙,一把钥匙只能开一个门,而高级程序员就会“造”万能钥匙。
我以前所理解的“简单”就是一把钥匙开一把锁的模式,仅仅只是着眼于解决现在的问题,而设计模式的“复杂”在于它需要造出具有“通用性”的万能钥匙。而我以前写的代码就是前者,这个“简单”不是功能的简单,而是设计的简单。简单的设计意味着缺少灵活性,代码很钢硬,仅仅只是面向过程,一步操作紧挨着下一步。
要使代码可被反复使用,请用’设计模式’对你的代码进行设计.
模拟鸭子程序开始了。
首先来一张类图,这是鸭子程序原始状态
而此时我们需要添加一个新功能:鸭子飞功能(吐槽:明明很多鸭子不会飞)
这很简单,难不倒我们“有OO思想”的人
但这样的设计运用在下面拓展的程序上会变成什么呢?
哇哦,很明显橡皮鸭子不能飞,而在此设计中使用继承(extends)就变得不合理了,
但是我们可以投机取巧一点,变成如下图
这样小聪明的方法,恐怕我自己看的都不能直视了....
很明显对于继承在这个设计当中很几个致命的地方
1:各个鸭子子类继承父类时,使得代码在多个子类中重复
2:没有拓展性,对于改变会费劲
3:往往改变一点地方很多地方就都要跟着改变,找出其他鸭子类中不想要的改变,牵一发而动全身。
设计原则一:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
注:当每次有新的需求的时候,就会使某方面发生变化,那么你就可以确定,这部分的代码就需要被抽出来,和其他稳定的代码有所区分,这样使得代码变化引起的不经意后果变少,系统变得更加富有弹性。
设计原则二:针对接口编程,而不是针对实现编程。
注:从现在开始我们编写的代码要富有弹性,让其运行时能“动态”的改变飞行或者呱呱叫行为
进行一点小改变
这里将飞行和叫的行为各自“抽象”出来成接口,这两个行为被分开成两个类,这两个类专门为提供某行为的实现提供接口。不同与之前设计:行为来自Duck父类中子类的具体实现,或是继承某个接口并由子类自行实现而来。这两种做法都依赖“实现”。而此时子类将使用接口所代表的行为,所以实际的“实现”不会被绑死在鸭子的子类中。(特定的具体行为编写在实现了FlyBehavior和QuackBehavior接口的实现类中)
这里放出具体行为设计
注:此时飞行和叫的动作(接口)可以被其他对象复用,此时这两个行为和鸭子类(Duck)无关了,而且往后加入新的行为也不怕了大量修改代码了。
鸭子父类:
package Entity; import Interface.FlyBehavior; import Interface.QuackBehavior; //鸭子父类 public class Duck { // 添加两个接口变量 FlyBehavior flyBehavior;// 每只鸭子都会引用完成FlyBehavior接口的对象 QuackBehavior quackBehavior;// 每只鸭子都会引用完成QuackBehavior接口的对象 public FlyBehavior getFlyBehavior() { return flyBehavior; } public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public QuackBehavior getQuackBehavior() { return quackBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } public Duck() { } public void swim() { System.out.println("鸭子游泳。。。。。。"); } // 动作 public void display() { System.out.println("每只鸭子都会动"); } // 这些方法取代fly(),quack() // 鸭子对象不亲自处理呱呱呱叫行为,而是委托给quackBehavior引用对象 public void performQuack() { quackBehavior.quack(); } // 鸭子对象不亲自处理飞行为,而是委托给flyBehavior引用对象 public void performFly() { flyBehavior.fly(); }; }
飞行和叫动作接口
package Interface; //飞行接口 public interface FlyBehavior { public void fly(); }
package Interface; //鸭子叫接口 public interface QuackBehavior { public void quack(); }
//绿头鸭和橡皮鸭类
package Entity; import Implements.FlyWithWings; import Implements.Quack; //绿头鸭子类 public class MallardDuck extends Duck { @Override public void display() { System.out.println("绿头鸭子"); } /* 当MallardDuck被实例化时, * 构造器会把继承来的quackBehavior,flyBehavior * 实例变量初始化成Quack,FlyWithWings的类型 * Quack,FlyWithWings分别是接口的实现类 * */ public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); } }
package Entity; import Implements.FlyNoWay; import Implements.Squeak; public class RubberDuck extends Duck { //橡皮鸭类 @Override public void display() { System.out.println("我是一只橡皮鸭"); } public RubberDuck() { quackBehavior = new Squeak(); flyBehavior = new FlyNoWay(); } }
各个行为的具体实现类,都实现了接口
package Implements; import Interface.FlyBehavior; public class FlyNoWay implements FlyBehavior { @Override public void fly() { System.out.println("不会飞"); } }
package Implements; import Interface.FlyBehavior; public class FlyWithWings implements FlyBehavior { @Override public void fly() { System.out.println("鸭子飞起来了。。。。。。"); } }
package Implements; import Interface.QuackBehavior; public class MuteQuack implements QuackBehavior { @Override public void quack() { System.out.println("不会叫"); } }
package Implements; import Interface.QuackBehavior; public class Quack implements QuackBehavior { @Override public void quack() { System.out.println("鸭子呱呱呱叫。。。。。。"); } }
package Implements; import Interface.QuackBehavior; public class Squeak implements QuackBehavior { @Override public void quack() { System.out.println("鸭子吱吱吱叫。。。。。。"); } }
测试类
package TestMain; import Entity.Duck; import Entity.MallardDuck; import Entity.RubberDuck; public class TestMain { public static void main(String[] args) { //这里使用多态,让Duck知道我们要创建一只绿头鸭 Duck d = new MallardDuck(); //重载方法 d.display(); d.performQuack(); d.performFly(); System.out.print(" "); Duck a=new RubberDuck(); a.display(); a.performQuack(); a.performFly(); } }
效果:
设计原则三:多用组合,少用继承。
注:使用组合建立系统具有很大的弹性,不仅可将算法封装成类,更可以“动态的改变行为”,只要组合对象符合正确的接口标准即可。
此时我刚刚写的例子基于一个策略模式思想写的。当然你可能会问:“用这个设计模式到底有什么用呢?这样功能我也能实现了,干嘛要搞的那么复杂?”。对此我不能用专业的思想去回答这样的疑问,我只能说随着自己学习的不断深入往往很多以前自认为对的东西,其实是不正确的。
策略模式要点:
1:良好的OO设计必须具备可复用性、可扩充性、可维护性三个特征
2:模式不是代码,而是针对设计问题的通用解决方案。
3:大多数的模式都允许系统局部改变独立于其他部分。
4:记着把系统中会改变的部分抽出来封装
5:模式会让开发人员之间有共同的语言,而且会让自己少走很多坑
这里我想说一点,很多人都觉得设计模式跟算法一样都是可有可无的东西,我觉得用设计模式是着眼于未来,可以提高系统的扩展性,减少重复劳动,虽然有的时候可能会增加工作量,但比起后期无止境的维护,这点反而不算什么,而设计模式是不会提高系统运行速度的,但我认为设计模式非常重要,包括带我的前辈程序员都教导我脑中要有模式概念,当然这个要因人而异。
感谢你看到这里,策略模式部分结束,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~很快我会发布下一个设计模式内容,生命不息,编程不止!
参考书籍:《Head First 设计模式》
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67596.html
摘要:本篇主要讲述中使用函数来实现策略模式和命令模式,最后总结出这种做法背后的思想。 《流畅的Python》笔记。本篇主要讲述Python中使用函数来实现策略模式和命令模式,最后总结出这种做法背后的思想。 1. 重构策略模式 策略模式如果用面向对象的思想来简单解释的话,其实就是多态。父类指向子类,根据子类对同一方法的不同重写,得到不同结果。 1.1 经典的策略模式 下图是经典的策略模式的U...
摘要:设计模式的定义在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。从前由于使用的局限性,和做的应用相对简单,不被重视,就更谈不上设计模式的问题。 ‘从大处着眼,从小处着手’,以前对这句话一知半解,自从踏出校门走入社会,开始工作以来,有了越来越深的理解,偶有发现这句话用在程序开发中也有用,所以,近段时间开始尝试着分析jQuery源码,分析angularjs源码,学习设计模式。 设...
摘要:下图就是第一版当时的样子年围绕他们的发起了积极的营销策略,比如像前文提到的那两次小花招,借此向人们进一步传递了的主张。从年到年,的销售效率指数始终大于,这说明公司在销售与营销上的花的每一美元都至少会收回一美元或更多的回报。 让我们回到17年前,那天软件服务商Siebel正在进行其用户会议。看起来一切都是安安静静的,但是加州从来就不会一直这么安静,因为这里有好莱坞也有硅谷。突然间,Siebel...
摘要:下图就是第一版当时的样子年围绕他们的发起了积极的营销策略,比如像前文提到的那两次小花招,借此向人们进一步传递了的主张。从年到年,的销售效率指数始终大于,这说明公司在销售与营销上的花的每一美元都至少会收回一美元或更多的回报。 让我们回到17年前,那天软件服务商Siebel正在进行其用户会议。看起来一切都是安安静...
摘要:继续我们的设计模式学习,有个好的观察者可以让你开发效率大大提高直接进入正题,我们用一个气象站程序来模拟此模式。内置了观察者模式的实现。 继续我们的设计模式学习,有个好的观察者可以让你开发效率大大提高 直接进入正题,我们用一个气象站程序来模拟此模式。有一个气象站程序,能对湿度,温度,气压进行监测并显示在显示装置上面模拟图如下,此系统中有三个部分气象站:获取实际气象数据的装置Weather...
阅读 2106·2021-11-05 09:42
阅读 2851·2021-09-23 11:21
阅读 2841·2019-08-30 14:00
阅读 3314·2019-08-30 13:15
阅读 465·2019-08-29 17:18
阅读 3547·2019-08-29 16:29
阅读 2749·2019-08-29 14:06
阅读 2794·2019-08-23 14:41