新萄京设计模式之策模式。读headFirst设计模式,headfirst设计模式。

昨天学习了设计模式中的策略模式,Joe所在的公司决定开发一款模拟鸭子的应用


宣读headFirst设计模式,headfirst设计模式

微人早就解决您的问题了

哟是设计模式?我们怎么而采取设计模式?怎样使用?按照书及的传教和自要好的明白,我道是如此的:我们遇到的问题外开发人员也碰到了,他们下他们之聪明和经历用问题化解了,把她们缓解问题之法门提炼总结出要该会解决任何同类问题。使用设计模式是以重新方便快捷的化解问题。把模式装上头脑里,然后于公的计划及曾经有些以被,寻找何处可以下这些模式,以往凡是代码复用,现在凡经历复用。

事先把开及之事例过千篇一律所有,简单的鸭子模拟下

Joe所当的铺决定开发同慢慢悠悠仿照鸭子的采取。系统面临生各种鸭子,鸭子可以游泳,可以可以,各种鸭子有两样的外观。此网建立了一个鸭子的基类,其中有游泳的方式swim,有呱呱叫的法子quack,有显鸭子外貌的主意display。每种鸭子的面相不同,必须于那个子类中再写display方法。就像这么:

新萄京 1

由于竞争加剧,公司说了算将定不平等的东西:“嘿,Joe,我思念鸭子应该会飞!”,“嗯,
这个听起颇易”,在Duck中加以一个fly方法就是执行了。过了几乎天,公司开会,“Joe,怎么会发生一样单纯橡皮鸭(RubberDuck,不见面奇怪,吱吱叫)在屏幕中飞来飞去?”,好吧,这是Joe疏忽了,只有真正的鸭能飞,橡皮鸭会为,会游泳但是未会见意外,马上修复(覆盖RubberDuck中的fly方法,
让她什么为未做)。但是要是自身待平等独诱饵鸭(DecoyDuck,不见面奇怪为非会见让)呢,也以子类中另行写quack和fly方法?Joe还接到通知,此系统还会见不定时更新,至于怎么创新还尚无想到,于是Joe意识及连续不是一个好办法,因为各个添加一个鸭的子类,他将要被迫检查该子类的quack和fly方法并可能得重写他们,如果直白修改父类中之不二法门,但多少子类并无思量修改,那么这些子类就还如又写这些艺术。

 

继往开来所用的代码

Duck

新萄京 2

public abstract class Duck {
    public void quack(){
        System.out.println("呱呱叫");
    }

    public void swim(){
        System.out.println("游泳");
    }

    //每个鸭子的外观不同, 在子类中实现
    public abstract void display();

    //鸭子飞行的方法
    public void fly(){
        System.out.println("飞行");
    }
}

View Code

MallardDuck

新萄京 3

/**
 * 外观是绿色的鸭子
 */
public class MallardDuck extends Duck {

    @Override
    public void display() {
        System.out.println("绿头鸭");
    }

}

View Code

RubberDuck

新萄京 4

/**
 * 橡皮鸭
 * 橡皮鸭不会呱呱叫(quack), 而是吱吱叫(squeak)
 */
public class RubberDuck extends Duck {

    @Override
    public void display() {
        System.out.println("可爱的黄色橡皮鸭");
    }

    //橡皮鸭不会呱呱叫(quack), 而是吱吱叫(squeak)
    @Override
    public void quack() {
        System.out.println("橡皮鸭吱吱叫");
    }

    //橡皮鸭不会飞
    @Override
    public void fly() {
    }
}

View Code

DecoyDuck

新萄京 5

/**
 * 诱饵鸭, 不会飞也不会叫
 */
public class DecoyDuck extends Duck {

    @Override
    public void display() {
        System.out.println("诱饵鸭");
    }

    @Override
    public void quack() {
        System.out.println("什么都不会做, 不会叫");
    }

    @Override
    public void fly() {
        System.out.println("什么都不做, 不会飞");
    }
}

View Code

 

利用接口也

拿行抽离出来,比如以fly方法抽离出来放到Flyable接口中,只有会奇怪的Duck的子类才实现该接口,同样的吗足以以quack方法抽离到Quackable接口中。就像这样:

新萄京 6

然解决了平等局部题目,至少橡皮鸭不见面四处飞了。但是若闹无来思了另外的一个问题,就是如此代码无法复用,因为接口中之方法才能够是空虚的,这样造成在每个子类中都需要再次写方法。这样的是从一个梦魇跳入了外一个梦魇。

 

转移以及未更换分离

哼吧,在软件开发上,有啊是若相信的,那就是是——change,不换的凡变。

尽管如此采取接口也不妥,但思想是值得借鉴的:
把转变之和非变换的离开,那哪是转的也?“真正的”鸭子会游泳swim,会呱呱叫quack,会飞fly,而橡皮鸭会游泳swim,会吱吱叫squeak,不会见奇怪。所以说被可以是地道,可以是吱吱叫,也可以无叫,飞可以顺着直线飞,可以本着曲线飞,也可不见面奇怪,所以给同意想不到是生成之。游泳都是以水面达随便规则之游,可以视作是勿换的,当然,你要是当游泳有多智,也得以当它是转的,我以此将游泳认为是匪转换的,所以说判断变化之以及免更换的只要因实际状况来定。

 

软件设计原则: 变化以及未更换分离

探寻有用中或许会见变卦之有些,把它独立出来,不要管她们和那些不变换的乱在齐。即把施用中或许会见生成之抽离出来并包起来。

 

承设计

冲变化与免转移分离的尺度,我们得以把转变之(飞和给)抽离出来并包起来。比如用航空的行事抽离出来设计成一个接口FlyBehavior,将给的一言一行设计改为接口QuackBehavior,然后实际的行事实现接口并再度写方法,如:

新萄京 7

 

 

对接口编程

咱俩将鸭的行于鸭子类Duck中分别出来,和往不同,以往之做法是:行为是起Duck中的现实贯彻持续过来,或是实现接口重写方法而来,这点儿种植方法还负实现,我们被实现绑得死死的。在咱们新的统筹中,我们拿作为分离出来,所以作为未见面绑死在鸭子的子类中,换句话说现实表现的代码位于特定类QuackBehavior和FlyBehavior中,可以于运转时动态的变更行为。这就是是对准接口编程的均等种体现,针对接口编程指的是对准超类型编程,不必然是interface,可以是abstract
class。

 

软件设计原则:针对接口编程

针对接口编程,而无是针对落实编程

 

重组实现代码

率先是个别个表现接口QuackBehavior和FlyBehavior

QuackBehavior

新萄京 8

public interface QuackBehavior {
    void quack();
}

View Code

 

FlyBehavior

新萄京 9

/**
 * 飞行行为接口
 */
public interface FlyBehavior {
    void fly();
}

View Code

 

QuackBehavior具体表现实现,呱呱叫Quack,吱吱叫Squeak,不见面让MuteQuack

Quack

新萄京 10

/**
 * 呱呱叫
 */
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("呱呱叫");
    }
}

View Code

 

Squeak

新萄京 11

/**
 * 吱吱叫
 */
public class Squeak implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("吱吱叫");
    }
}

View Code

 

MuteQuack

新萄京 12

/**
 * 什么都不做, 不会叫
 */
public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("什么都不做, 不会叫");
    }
}

View Code

 

FlyBehavior的有血有肉实现,用翼飞FlyWithWings,不会见飞FlyNoWay

FlyWithWings

新萄京 13

/**
 * 用翅膀飞
 */
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("用翅膀飞行");
    }
}

View Code

 

FlyNoWay

新萄京 14

/**
 * 不会飞
 */
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("什么都不做, 不能飞");
    }
}

View Code

 

然后是基类Duck,将作为接口当做实例变量放入Duck中,需要以运行时动态的变动行为,可以提供setter方法

Duck

新萄京 15

public abstract class Duck {
    //针对接口编程的体现
    private FlyBehavior flyBehavior;
    private QuackBehavior quackBehavior;

    //设置一个默认的行为
    public Duck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }

    public void swim(){
        System.out.println("游泳");
    }

    //每个鸭子的外观不同, 在子类中实现
    public abstract void display();

    //执行呱呱叫的方法
    public void performQuack(){
        quackBehavior.quack();
    }

    //执行飞行的方法
    public void performFly(){
        flyBehavior.fly();
    }


    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

View Code

留神,抽象类为是来构造方法的,不过未可知创建对象,抽象类的构造方法是为此来初始化变量的

 

片独子类MallardDuck和RubberDuck

MallardDuck

新萄京 16

/**
 * 外观是绿色的鸭子
 */
public class MallardDuck extends Duck {

    @Override
    public void display() {
        System.out.println("绿头鸭");
    }

    @Test
    public void test1() throws Exception {
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.performQuack();
        mallardDuck.performFly();
        display();
    }
}

View Code

 

RubberDuck

新萄京 17

/**
 * 橡皮鸭
 * 橡皮鸭不会呱呱叫(quack), 而是吱吱叫(squeak)
 */
public class RubberDuck extends Duck {
    @Override
    public void display() {
        System.out.println("可爱的黄色橡皮鸭");
    }

    @Test
    public void test1() throws Exception {
        Duck rubberDuck = new RubberDuck();
        //运行时动态改变行为
        rubberDuck.setFlyBehavior(new FlyNoWay());
        rubberDuck.setQuackBehavior(new Squeak());
        rubberDuck.performFly();
        rubberDuck.performQuack();
        rubberDuck.display();
    }
}

View Code

 

装进行为

好了,我们来看望整体的布置:飞行行为实现了FlyBehavior接口,呱呱叫行为实现了QuackBehavior接口,也要留心,我们讲述事务的办法也负有转,我们拿作为当作一组算法,飞行行为是算法,呱呱叫行为呢是算法,就比如这么:

新萄京 18

 

咱们把QuackBehavior和FlyBehavior类型的变量放到了Duck中,这实则就是用到了咬合。用结合创建的系更具有弹性,不会见要连续一般同样地处改动可能用多介乎改动

 

软件设计原则:

差不多用整合,少用连续

 

策略模式

好了,到此地我们毕竟学到了第一只模式:策略模式(strategy
pattern),介绍一下方针模式之概念

概念了好不容易法族,并分别封装起来,让他们中可相互替换,此模式被算法的别独立于下算法的客户

 

http://www.bkjia.com/Javabc/1186192.htmlwww.bkjia.comtruehttp://www.bkjia.com/Javabc/1186192.htmlTechArticle读headFirst设计模式,headfirst设计模式
有些人早就缓解你的题目了
什么是设计模式?我们为什么要动用设计模式?怎样用?按照书及之说…

直接惦念将大的设计模式系统地读书一全副,结果以及多数口同样,过了几天就从不能坚持下去了。我意识上这宗业务急不得,往往你更加着急便愈容易半途而废。反而是沉住气,一上修一些,然后将其置身脑子里,在碎片时间里“拿”出来捋一捋,像发酵一样,渐渐地接消化也投机的事物,然后又起念下一个知识点。好了,闲话说了如此多,我们开吧!


昨天上学了设计模式中的政策模式,这个模式的沉思就是是:

  • 面向接口编程
  • 把用中可能用扭转的远在单独出来,不要同那些无欲扭转之代码乱在共。

咱们重来看望维基百科对于c策略模式之概念:

策模式作为同种植软件设计模式,指目标有有行为,但是在不同之景被,该行为出不同的兑现算法。比如每个人且使“交个人所得税”,但是“在美国到个人所得税”和“在中国暨个人所得税”就发不同之算税方法。
政策模式:
概念了同一族算法(业务规则);
包了每个算法;
这族的算法可互换代替(interchangeable)


圈之一知半解的,我们由此一个例证来深切之衡量之神奇的设计模式。
情景:一个模拟游戏中需要采取很多差档次的鸭子,请编写代码以变更不同之鸭子对象。

君或许想到编一个Duck抽象超类然后给现实的鸭类去继续其,在子类中再次写超类中之计,实现“个性化”,于是你写的代码可能就是是下这法的:

public class Duck{
  public void quack(){
//鸭子的叫声
}
  public void swim(){
//鸭子会游泳
}
  public display(){
//鸭子的羽毛的颜色
}

下一场再度定义一个子类:

public class MallardDuck extends Duck{
  public void display(){
    System.out.println("我的羽毛是绿色的");
}
}

初一关押好像感觉并无什么尴尬啊?确实上面这种写法在列的头可能真正能够及用户突出的要求,但是需要是可能转变之,你应有考虑的是:当求变动之上你的代码是否会活应对,这当工程达到称低耦合。

依照,现在求变动了,我如果有一致种植会奇怪的鸭,怎么惩罚?你或会见说马上出什么难以之,在Duck类里面上加一个fly方法不纵可了也?但是乍的问题又来了:如果你于超类设置了fly方法,就意味着每一个子类都见面有fly方法,这自然不能够忍心啊,你恐怕还要见面想到补救措施:在那些不会见飞的鸭子类中又写一全勤fly方法。这样好是好,如果400种植鸭有200种不见面意外的鸭子类,可能而成天都当那边开还写工作了。

那因此接口也?让那些会奇怪的鸭子实现接口中之fly方法?这就是超人的起一个坑跳到了另外一个坑,你本将拿会见奇怪的那200种植鸭都使兑现均等全fly方法。


好了,上面我们拿题目且梳理了一如既往任何。我们更审视一不成我们遇到的问题。在例子中,总共有点儿栽飞行行为:会奇怪的与未会见奇怪的。我们好免把她形容上类里,因为咱们就看,不同鸭子的飞行行为是免相同的。这就是咱地方提到的把要转变之一对提取出。其实这是设计模式中非常要紧之一个统筹规范:差不多用结合,少用连续。我们设计一个飞行接口,让现实的飞行行为看似去落实它,到底怎么竟由接近自己实现。而我们的Duck类将飞接口当成是鸭子的一个成员变量。由于Duck类知道之飞行行为接口肯定起一个fly方法,所以我可大胆之在Duck类里面调用这个变量的fly方法(这就是是面向接口编程),而实际怎么竟要出于现实的宇航行为来控制,这当Java中叫终绑定

规律讲清楚了,上代码:

鸭子类:

public abstract class Duck {
    protected FlyBehavior flyBehavior;   
    protected QuackBehavior quackBehavior; 
    public abstract void display(); 
    public void performQuack(){ 
    quackBehavior.quack();  
   }    
    public void performFly(){  
      flyBehavior.fly(); 
   }    
    public void swim(){   
     System.out.println("所有的鸭子都能漂浮于水面。");  
   } 
    public void setFlyBehavior(FlyBehavior flyBehavior){ 
        this.flyBehavior=flyBehavior;  //为了代码更加灵活,这里添加设置 
 飞行行为的方法,下同
   }  
    public void  setQuackBehavior(QuackBehavior quackBehavior){  
      this.quackBehavior=quackBehavior;  //修改鸭子的叫声,有的呱呱叫,有的小鸭还不会叫
  }
}

飞行行为接口:

public interface FlyBehavior {
    void fly();
}

叫声接口:

public interface QuackBehavior { 
   void quack();
}

切实的飞行行为类one:

public class FlyWithWings implements FlyBehavior {
    public void fly(){
        System.out.println("我可以飞。");
    }
}

实际的宇航行为类two:

public class FlyNoWay implements FlyBehavior {
    public void fly(){
        System.out.println("我不能飞");
    }
}

具体的被声类one:

public class Quack implements QuackBehavior {
    public void quack(){
        System.out.println("呱呱叫");
    }
}

实际的让声类two:

public class MuteQuack implements QuackBehavior {
    public void quack(){
        System.out.println("<我不能叫>");
    }
}

哼了,部件代码都勾好了,我们来讲它组装组装:

野鸭:

public class MallardDuck extends Duck {
    public MallardDuck(){
        quackBehavior=new Quack();
        flyBehavior=new FlyWithWings();
    }
    public void display(){
        System.out.println("我是野鸭");
    }
}

模型鸭(假的鸭):

public class ModelDuck extends Duck {
    public ModelDuck(){
        setFlyBehavior(new FlyNoWay());
        setQuackBehavior(new MuteQuack());
    }
    public void display(){
        System.out.println("我是模型鸭");
    }
}

咱俩可感受及,经过改写后的代码灵活多了,这种活主要是缘于可以动态新萄京的组合鸭子的行为,而非死的接续方式。


我们重新复习一下策略模式之几乎独计划原则作最后吧:

  • 面向接口编程,而未面向实现编程
  • 大多用整合,少用持续
  • 抽离易改变之代码

自己是在校学员,目前大三,如发生描绘的非正常的地方,欢迎指正,谢谢!另外,设计模式文章准备写成一个系列,欢迎follow(
\_ )