武汉理工大学 软件设计与体系结构 32设计模式 整理

这个部分内容比较多,单独开一章来整理

32.掌握:
1.命令模式
2.状态模式,
3.装饰模式,
4.观察者模式,
5.策略模式,
6.单例模式,
7.工厂方法模式,
8.抽象工厂模式,
9.组合模式
10.适配器模式,
11.外观模式,
12.责任链模式
的UML图和java代码
凡是课件里有关架构的具体例子
(一般都有UML图或有代码)都需要仔细体会,重点搞清楚实验指导书里的各个步骤过程怎么做的。

1.命令模式(别名:动作,事务)

  • 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

  • 概述:在许多设计中,经常涉及到一个对象请求另一个对象调用其方法到达某种目的。如果请求者不希望或无法直接和被请求者打交道,即不希望或无法含有被请求者的引用,那么就可以使用命令模式。

  • 实例:在军队作战中,指挥官请求三连偷袭敌人,但是指挥官不希望或无法直接与三连取得联系,那么可以将该请求:“三连偷袭敌人”形成一个“作战命令”。只要能让该作战命令被执行,就会实现三连偷袭敌人的目的。

  • 模式的结构中包括四种角色
    接收者(Receiver)
    命令(Command)接口
    具体命令(ConcreteCommand)
    请求者(Invoker)

1.png

1.接收者(Receiver) : CompanyArmy.java

public class CompanyArmy{
   public void sneakAttack(){ 
      System.out.println("我们知道如何偷袭敌人,保证完成任务"); 
   }
}

2.命令(Command)接口 : Command.java

public interface Command {
   public abstract void execute();
}

3.具体命令(ConcreteCommand) ConcreteCommand.java

public class ConcreteCommand implements Command{
   CompanyArmy army;           //含有接收者的引用
   ConcreteCommand(CompanyArmy army){
      this.army=army;
   }
   public  void execute(){    //封装着指挥官的请求
      army.sneakAttack();     //偷袭敌人  
   }
}

4.请求者(Invoker) ArmySuperior.java

public class ArmySuperior{
  Command command;          //用来存放具体命令的引用
  public void setCommand(Command command){
     this.command=command;
  }
  public void startExecuteCommand(){ 
                     //让具体命令执行execute()方法
     command.execute();
  }
}

5.应用 Application.java

 public class Application{
   public static void main(String args[]){
      CompanyArmy 三连=new CompanyArmy();         
      Command command=new ConcreteCommand(三连);
      ArmySuperior 指挥官=new ArmySuperior();     
      指挥官.setCommand(command);                 
      指挥官.startExecuteCommand();
   }
}
  • 命令模式的优点
    在命令模式中,请求者(Invoker)不直接与接收者(Receiver)交互,即请求者(Invoker)不包含接收者(Receiver)的引用,因此彻底消除了彼此之间的耦合。
    命令模式满足“开-闭原则”。如果增加新的具体命令和该命令的接受者,不必修改调用者的代码,调用者就可以使用新的命令对象;反之,如果增加新的调用者,不必修改现有的具体命令和接受者,新增加的调用者就可以使用已有的具体命令。

  • 应用举例
    模拟带控制开关的小电器。该电器上有四个开关,两个一组,其中一组负责打开、关闭小电器上的照明灯,另一组负责打开、关闭小电器上的摄像头。

2.状态模式

状态模式(别名:状态对象)
允许一个对象在其内部状态改变时改变它的行为。
State Pattern(Another Name: Objects for States)
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

概述:一个对象的状态依赖于它的成员变量的取值情况。对象在不同的运行环境或运行时刻,可能具有不同的状态。在许多情况下,对象调用方法所产生的行为效果依赖于它当时的状态。
状态模式的关键是将对象的状态封装成为独立的类,对象调用方法时,可以委托当前对象所具有的状态(对象)调用相应的方法,使得当前对象看起来好像修改了它的类。

一个实例:

class Thermometer{//温度计类
    double temputer;
    public void showMessage(){
    if( temperature<=-20 )
    System.out.println(“现在温度是:”+temputer);
    else(temperature>=30)
    System.out.println(“现在温度是:”+temputer);
    }
}//如果用户要求temperature>60……?//分离对象状态

模式的结构中包括三种角色
环境(Context)
抽象状态(State)
具体状态(Concrete State)

4.png

1.环境(Context): Thermometer.java

public  class  Thermometer{
      TemperatureState  state;
       public  void  showMessage(){
            System.out.println("***********");
            state.showTemperature();  
            System.out.println("***********");
      }
      public void setState(TemperatureState  state){
            this.state=state;
      }
} 

2.抽象状态(State): TemperatureState.java

public  interface  TemperatureState{
      public void showTemperature();   
 } 

3.具体状态(Concrete State)_1:LowState.java

public class LowState implements TemperatureState{
       double n=0;
       LowState(double n){
            if(n<=0)
              this.n=n;
       }
       public void showTemperature(){
              System.out.println("现在温度是"+n+"属于低温度");
       }
}

3.具体状态(Concrete State)_2:MiddleState.java

public class MiddleState implements TemperatureState{
       double n=15;
       MiddleState(int n){
            if(n>0&&n<26)
               this.n=n;
       }
       public void showTemperature(){
              System.out.println("现在温度是"+n+"属于正常温度");
       }
}

3.具体状态(Concrete State)_3:HeightState.java

public class HeightState implements TemperatureState{
       double n=39;
       HeightState(int n){
            if(n>=39)
               this.n=n;
       }
       public void showTemperature(){
              System.out.println("现在温度是"+n+"属于高温度");
       }
}

4.应用 Application.java

 public class Application{
     public static void main(String args[]) {
           TemperatureState state=new LowState(-12);
           Thermometer  thermometer=new Thermometer();
           thermometer.setState(state);
           thermometer.showMessage();
           state=new MiddleState(20);
           thermometer.setState(state);
           thermometer.showMessage();
           state=new HeightState(39);
           thermometer.setState(state);
           thermometer.showMessage();
     }
}

状态切换:
一个使用弹夹大小为3颗子弹的手枪通过更换弹夹重新获取子弹。使用弹夹的大小位3颗子弹的手枪共有4种状态:有3颗子弹,有2颗子弹,有1颗子弹,没有子弹。手枪只有在有子弹的状态下可以调用fire()方法进行射击,只有在没有子弹的状态下可以调用LoadBullet()方法装载新弹夹获得子弹。需要注意的是,手枪调用fire()方法和LoadBullet()都会导致手枪的状态发生变换。

image.png

1.环境(Context): Gun.java

public  class  Gun{
       State  stateThree,stateTwo,stateOne,stateNull,state;
       public  void  Gun(){
            stateThree=new BulletStateThree(this);
        stateTwo=new BulletStateTwo(this);
        stateOne=new BulletStateOne(this);
        stateNull=new BulletStateNull(this);
        state=stateThree;
      }
      public void setState(State  state){
            this.state=state;
      }

1.环境(Context): Gun.java

public void fire(){state.fire();}
public void State getBulletStateThree(){
    return stateThree;}
public void State getBulletStateTwo(){
    return stateTwo;}
public void State getBulletStateOne(){
    return stateOne;}
public void State getBulletStateNull(){
    return stateNull;}

2.抽象状态(State): State.java

public  interface  State{
      public void fire(); 
    public void LoadBullet();
    public String showStateMess();  
 } 

3.具体状态(Concrete State)_1:BulletStateThree.java

public class BulletStateThree implements State{
    Gun gun;
    BulletStateThree(Gun gun){this.gun=gun;}
    public void fire(){
    System.out.print(“打出一个子弹”);
·   gun.setState(gun.getBulletStateTwo());//new BulletStateTwo()?
    public void loadBullet(){System.out.println(“无法装弹”);}
    public String showStateMess(){return “2个子弹状态”;}
}

3.具体状态(Concrete State)_2:BulletStateTwo.java

public class BulletStateTwo implements State{
    Gun gun;
    BulletStateThree(Gun gun){this.gun=gun;}
    public void fire(){
    System.out.print(“打出1个子弹”);
·   gun.setState(gun.getBulletStateOne());
    public void loadBullet(){System.out.println(“无法装弹”);}
    public String showStateMess(){return “1个子弹状态”;}
}

3.具体状态(Concrete State)_1:BulletStateOne.java

public class BulletStateTwo implements State{
    Gun gun;
    BulletStateOne(Gun gun){this.gun=gun;}
    public void fire(){
    System.out.print(“打出1个子弹”);
·   gun.setState(gun.getBulletStateNull());
    public void loadBullet(){System.out.println(“无法装弹”);}
    public String showStateMess(){return “1个子弹状态”;}
}

3.具体状态(Concrete State)_1:BulletStateNull.java

public class BulletStateTwo implements State{
    Gun gun;
    BulletStateOne(Gun gun){this.gun=gun;}
    public void fire(){System.out.print(“不能打出子弹”);}
·   gun.setState(gun.getBulletStateNull());
    public void loadBullet(){
    System.out.println(“装弹”);
    gun.setState(gun.getBulletStateThree());}
    public String showStateMess(){return “无子弹状态”;}
}

3.Application: Application.java

public class Application {
    public static void main(String args[]){
    Gun gun=new Gun();
    gun.fire(); gun.fire(); gun.fire(); gun.fire();
    gun.LoadBullet();
    }
}

共享状态:
一列客运列车的卧铺车厢和普通车厢共享运动和静止状态,车厢可以由静止状态切换到运行状态,也可以由运行状态切换到静止状态,当卧铺车厢从运动状态切换到静止状态候,普通车厢自然也是静止状态,反之亦然。

1.Vehicle: Vehicle.java

public class Vehicle {
    static State state,moveState,restState;
    String name;
    Vehicle(String name){
    this.name=name;moveState=new VehicleMoveState();
    restState=new VehicleRestState();state=restState;}
    public void startUp(){state.startUp(this);}
    public void stop(){state.stop(this);}
    public void setState(State state){this.state=state;}
    public State getMoveState(){return moveState;}
    public State getRestState(){return restState;}
    public String getName(){return name;}
}

2.抽象状态(State): State.java

public  interface  State{
      public void startUp( Vehicle vehicle); 
    public void stop(Vehicle vehicle);
 } 

3.具体状态(Concrete State)_1:VehicleMoveState.java

public class VehicleMoveState extends State{
     public void startUp(Vehicle vehicle){
    System.out.println(vehicle.getName()+”已经处于运动状态了”);}
    public void stop(Vehicle vehicle){
    System.out.println(vehicle.getName()+”停止运动”);
    vehicle.setState(vehicle.getRestState());}
}

3.具体状态(Concrete State)_1:VehicleRestState.java

public class VehicleRestState extends State{
     public void stop(Vehicle vehicle){
    System.out.println(vehicle.getName()+”已经处于静止状态了”);}
    public void startUp (Vehicle vehicle){
    System.out.println(vehicle.getName()+”开始运动”);
    vehicle.setState(vehicle.getMoveState());}
}

3.Application: Application.java

public class Application {
    public static void main(String args[]){
    Vehicle carOne=new Vehicle(“卧铺车厢”);
    Vehicle carTwo=new Vehicle(“普通车厢”);
    carOne.startUp();carTwo.startUp();
    carTwo.stop();carOne.stop();
    }
}

状态模式的优点

  • 使用一个类封装对象的一种状态,很容易增加新的状态。
  • 在状态模式中,环境(context)中不必出现大量的条件判断语句。环境(context)实例所呈现的状态变得更加清晰、容易理解。
  • 使用状态模式可以让用户程序很方便的切换环境(context)实例的状态。
  • 使用状态模式不会让环境(context)的实例中出现内部状态不一致的情况。
  • 当状态对象没有实例变量时,环境(context)的各个实例可以共x享一个状态对象。

一个实例:
咖啡自动售货机共有三种状态,分别是:有咖啡,无人投币;有咖啡,有人投币;无咖啡。咖啡自动售货机有两个方法:showMessage()和giveAnCupCaffee()。
咖啡自动售货机的默认状态是:有咖啡,无人投币。当售货机处于有咖啡,无人投币状态时,调用showMessage()方法将显示“请您投入一元硬币”;当用户投入一元硬币后,咖啡自动售货机将处于有咖啡,有人投币的状态。此时调用giveAnCupCaffee()方法,用户将得到一杯咖啡。然后咖啡自动售货机将处于有咖啡无人投币状态或无咖啡状态;当咖啡自动售货机处于无咖啡或有咖啡无人投币状态时,调用giveAnCupCaffee()方法不会得到咖啡。

3.装饰模式

  • 装饰模式(别名:包装器)
    动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。
    Decorator Pattern(Another Name: Wrapper)
    Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

  • 概述:装饰模式是动态地扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。在装饰模式中,“具体组件”类和“具体装饰”类是该模式中的最重要的两个角色。

  • 实例:
    假设系统中有一个Bird抽象类以及Bird类的一个子类:Sparrow。
    Sparrow类实现了Bird类的fly方法,使得Sparrow类创建的对象
    调用fly方法能连续飞行100米。现在用户需要两种鸟,必须分别
    能连续飞行150米和200米。

装饰模式的结构中包括四种角色
抽象组件(Component)
具体组件(ConcreteComponent)
装饰(Decorator)
具体装饰(ConcreteDecotator)

3.png

1.抽象组件 : Bird.java

public abstract class Bird{
   public abstract int fly();
}

2.具体组件 : Sparrow.java

public class Sparrow extends Bird{
   public final int DISTANCE=100;
   public int fly(){
      return DISTANCE;
   }
}

3.装饰 (Decorator): Decorator.java

public abstract class Decorator extends Bird{
    protected Bird bird;
    public Decorator(){
    }
    public Decorator(Bird bird){
       this.bird=bird; 
    }
}

4.具体装饰(ConcreteDecotator): SparrowDecorator.java

public class  SparrowDecorator extends Decorator{
   public final int DISTANCE=50;        //eleFly方法能飞50米
   SparrowDecorator(Bird bird){
      super(bird);
   }
   public int fly(){
      int distance=0;
      distance=bird.fly()+eleFly(); 
      return distance; 
   }
   private int eleFly(){              //装饰者新添加的方法
      return DISTANCE;
   }
} 

5.应用 Application.java

 public class Application{
   public void needBird(Bird bird){
       int flyDistance=bird.fly();
       System.out.println("这只鸟能飞行"+flyDistance +"米");  
   }
   public static void main(String args[]){
      Application client=new Application ();    
      Bird sparrow=new Sparrow();          
      Bird sparrowDecorator1=
      new SparrowDecorator(sparrow);       
      Bird sparrowDecorator2=
      new SparrowDecorator(sparrowDecorator1); 
      client.needBird(sparrowDecorator1); 
      client.needBird(sparrowDecorator2);                
  }
}
  • 装饰模式的优点
    被装饰者和装饰者是松耦合关系。由于装饰(Decorator)仅仅依赖于抽象组件(Component),因此具体装饰只知道它要装饰的对象是抽象组件的某一个子类的实例,但不需要知道是哪一个具体子类。
    装饰模式满足“开-闭原则”。不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。
    可以使用多个具体装饰来装饰具体组件的实例。

  • 应用举例
    当前系统已有一个抽象类ReadWord,该类有一个抽象方法readWord(),另外还有一个ReadWord类的子类ReadEnglishWord,该类的readWord()方法可以读取一个由英文单词构成的文本文件word.txt。系统已有类的类图如图6.11所示。目前已有一些客户在使用该系统,并使用ReadWord类的对象调用readWord()方法读取文件中的单词。

4.png

现有部分用户希望使用ReadWord类的对象调用readWord()方法读取文件word.txt中的单词,并希望同时也能得到该单词 的汉语解释,也有一些用户希望不仅能得到该单词汉语解释也能得到该单词的英文例句。要求不允许修改现有系统的代码以及word.txt文件,对系统进行扩展以满足用户需求。

4.观察者模式

  • 观察者模式(别名:依赖,发布-订阅)
    定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。
    Observer Pattern(Another Name: Dependents, Publish-Subscribe)
    Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically..

  • 概述:在许多设计中,经常涉及到多个对象都对一个特殊对象中的数据变化感兴趣,而且这多个对象都希望跟踪那个特殊对象中的数据变化。

  • 实例:某些寻找工作的人对“求职中心”的职业需求信息的变化非常关心,很想跟踪“求职中心”中职业需求信息的变化。“求职者”可以让“求职中心”把自己登记下来,这样求职中心就会及时通知她最新的职业信息需求。

观察者模式的结构中包括四种角色
主题(Subject)
观察者(Observer)
具体主题(ConcreteSubject)
具体观察者(ConcreteObserver)

2.png

1.主题 : Subject.java

   public interface Subject{
   public void addObserver(Observer o);
   public void deleteObserver(Observer o);
   public void notifyObservers();
}

2.观察者 : Obsever.java

public interface Observer{
   public void hearTelephone(String heardMess);
} 

3.具体主题 SeekJobCenter.java_1

  import java.util.ArrayList;                      
public class SeekJobCenter implements Subject{
    String mess;
    boolean changed;
    ArrayList<Observer> personList; 
    SeekJobCenter(){
       personList=new ArrayList<Observer>();
       mess=""; 
       changed=false; 
    }
    public void addObserver(Observer o){
       if(!(personList.contains(o)))
         personList.add(o); }
    public void deleteObserver(Observer o){
       if(personList.contains(o))
         personList.remove(o); 
    }

4.具体观察者_1 UniversityStudent.java

import java.io.*;
public class UniverStudent implements Observer{
   Subject subject;
   File myFile;  
   UniverStudent(Subject subject,String fileName){
      this.subject=subject;
      subject.addObserver(this);     //使当前实例成为subject所引用的具体主题的观察者
      myFile=new File(fileName);
   }
   public void hearTelephone(String heardMess){
      try{ RandomAccessFile out=new RandomAccessFile(myFile,"rw");  
           out.seek(out.length());
           byte [] b=heardMess.getBytes();
           out.write(b);                               //更新文件中的内容
           System.out.print("我是一个大学生,"); 
           System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
           System.out.println(heardMess); 
      }
      catch(IOException exp){
          System.out.println(exp.toString());
      }
  } 
}

4.具体观察者_2 HaiGui.java

import java.io.*;
import java.util.regex.*;
public class HaiGui implements Observer{
   Subject subject;
   File myFile;  
   HaiGui(Subject subject,String fileName){
      this.subject=subject;
      subject.addObserver(this);     //使当前实例成为subject所引用的具体主题的观察者
      myFile=new File(fileName);
   }
   public void hearTelephone(String heardMess){
      try{ boolean boo=heardMess.contains("java程序员")||heardMess.contains("软件");
           if(boo){ 
             RandomAccessFile out=new RandomAccessFile(myFile,"rw");  
             out.seek(out.length());
             byte [] b=heardMess.getBytes();
             out.write(b); 
             System.out.print("我是一个海归,"); 
             System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
             System.out.println(heardMess);
           }
           else{
              System.out.println("我是海归,这次的信息中没有我需要的信息");
           } 
      }
      catch(IOException exp){
          System.out.println(exp.toString());
      }
  } 
} 

5.应用 Application.java

public class Application{
   public static void main(String args[]){
      SeekJobCenter center=new SeekJobCenter();           
      UniverStudent zhangLin=new UniverStudent(center,"A.txt");
      HaiGui wangHao=new HaiGui(center,"B.txt");          
      center.giveNewMess("腾辉公司需要10个java程序员。");   
      center.notifyObservers();                              
      center.giveNewMess("海景公司需要8个动画设计师。");
      center.notifyObservers();
      center.giveNewMess("仁海公司需要9个电工。");
      center.notifyObservers();
      center.giveNewMess("仁海公司需要9个电工。");    
      center.notifyObservers();                       
}
  • 观察者模式的优点:
    具体主题和具体观察者是松耦合关系。由于主题(Subject)接口仅仅依赖于观察者(Observer)接口,因此具体主题只是知道它的观察者是实现观察者(Observer)接口的某个类的实例,但不需要知道具体是哪个类。同样,由于观察者仅仅依赖于主题(Subject)接口,因此具体观察者只是知道它依赖的主题是实现主题(subject)接口的某个类的实例,但不需要知道具体是哪个类。
    观察模式满足“开-闭原则”。主题(Subject)接口仅仅依赖于观察者(Observer)接口,这样,我们就可以让创建具体主题的类也仅仅是依赖于观察者(Observer)接口,因此如果增加新的实现观察者(Observer)接口的类,不必修改创建具体主题的类的代码。同样,创建具体观察者的类仅仅依赖于主题(Observer)接口,如果增加新的实现主题(Subject)接口的类,也不必修改创建具体观察者类的代码。

  • 应用举例
    指挥部希望按时得到水文站测量到的关于水流的信息,比如流量、流速等。

5.策略模式

策略模式(别名:政策)
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
*Strategy Pattern(Another Name: Policy)
Define a family of algorithms, encapsulate each one, and make them inter changeable. Strategy lets the algorithm vary independently from clients that use it. *

  • 概述
    策略模式是处理算法的不同变体的一种成熟模式,策略模式通过接口或抽象类封装算法的标识,即在接口中定义一个抽象方法,实现该接口的类将实现接口中的抽象方法。
    在策略模式中,封装算法标识的接口称作策略,实现该接口的类称作具体策略。

策略模式的结构中包括三种角色
策略(Strategy)
具体策略(ConcreteStrategy)
上下文(Context)

5.png

1.策略(Strategy) : Computable.java

public interface ComputableStrategy{
  public abstract double computeScore(double [] a);
} 

2.具体策略(ConcreteStrategy): StrategyOne.java

public class StrategyOne implements ComputableStrategy{
    public double computeScore(double [] a){
        double score=0,sum=0;
        for(int i=0;i<a.length;i++){
            sum=sum+a[i];
        }
        score=sum/a.length;
        return score; 
    }
}

2.具体策略(ConcreteStrategy): StrategyTwo.java

public class StrategyTwo implements ComputableStrategy{
    public double computeScore(double [] a){
        double score=0,multi=1;
        int n=a.length;
        for(int i=0;i<a.length;i++){
            multi=multi*a[i];
        }
        score=Math.pow(multi,1.0/n);
        return score; 
    }
}

2.具体策略(ConcreteStrategy): StrategyThree.java

import java.util.Arrays;
public class StrategyThree implements ComputableStrategy{
    public double computeScore(double [] a){
        if(a.length<=2)
            return 0;
        double score=0,sum=0;
        Arrays.sort(a);
        for(int i=1;i<a.length-1;i++){
           sum=sum+a[i]; 
        }
        score=sum/(a.length-2);
        return score; 
    }
}

3.上下文: GymnasticsGame.java

public class  GymnasticsGame{
     ComputableStrategy strategy;
     public void setStrategy(ComputableStrategy strategy){
         this.strategy=strategy;
     } 
     public double getPersonScore(double [] a){
        if(strategy!=null)
          return strategy.computeScore(a); 
        else
          return 0;
     }
}

4.应用: Application.java_1

 public class Application{
   public static void main(String args[]){
     GymnasticsGame game=new GymnasticsGame();   
     game.setStrategy(new StrategyOne());        
     Person zhang=new Person();
     zhang.setName("张三");
     double [] a={9.12,9.25,8.87,9.99,6.99,7.88};
     Person li=new Person();
     li.setName("李四");
     double [] b={9.15,9.26,8.97,9.89,6.97,7.89};   
     zhang.setScore(game.getPersonScore(a));
     li.setScore(game.getPersonScore(b));
     System.out.println("使用算术平均值方案:");
     System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore());
     System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore());
     game.setStrategy(new StrategyTwo());   
     zhang.setScore(game.getPersonScore(a));
     li.setScore(game.getPersonScore(b));
     System.out.println("使用几何平均值方案:");
     System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore());
     System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore()); 

4.应用: Application.java_2

    game.setStrategy(new StrategyThree());    
     zhang.setScore(game.getPersonScore(a));
     li.setScore(game.getPersonScore(b));
     System.out.println("使用(去掉最高、最底)算术平均值方案:");
     System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore());
     System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore());            
  }
}
class Person{
   String name;
   double score;
   public void setScore(double t){
      score=t;
   }
   public void setName(String s){
      name=s;
   }
   public double getScore(){
      return score;
   }
   public String getName(){
      return name;
   }
}
  • 策略模式的优点
    上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系。因此上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一个类。
    策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。

6.单例模式

单件模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Prototype Pattern
Ensure a class only has one instance, and provide a global point of access to it.

概述:单件模式是关于怎样设计一个类,并使得该类只有一个实例的成熟模式,该模式的关键是将类的构造方法设置为private权限,并提供一个返回它的唯一实例的类方法。

模式的结构中只包括一个角色
单件类(Singleton)

5.png

1.单件类(Singleton): Moon.java

public class Moon{
      private static Moon  uniqueMoon;
      double radius;
      double distanceToEarth;
      private Moon(){
           uniqueMoon=this;
           radius=1738;
           distanceToEarth=363300;
      }     
      public static synchronized Moon getMoon(){   
            if(uniqueMoon==null){
                  uniqueMoon=new Moon();
            }
            return uniqueMoon;
      }
      public String show(){
           String s="月亮的半径是"+radius+"km,距地球是"+distanceToEarth+"km";
           return s;
      }
}

2.应用 Application.java

import javax.swing.*;
import java.awt.*;
public class Application{
    public static void main(String args[]){
          MyFrame f1=new MyFrame("张三看月亮");
          MyFrame f2=new MyFrame( "李四看月亮");
          f1.setBounds(10,10,360,150);
          f2.setBounds(370,10,360,150);
          f1.validate();
          f2.validate();
    }
}
class  MyFrame extends JFrame{
    String str;
    MyFrame(String title){
        setTitle(title);
        Moon moon=Moon.getMoon();     
        str=moon.show();
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setVisible(true);
        repaint();
   } 
    public void paint(Graphics g){
          super.paint(g);
          g.setFont(new Font("宋体",Font.BOLD,14));
          g.drawString(str,5,100);
    }
}

单件模式的优点:
单件类的唯一实例由单件类本身来控制,所以可以很好地控制用户何时访问它。

7.工厂方法模式

工厂方法模式(别名:虚拟构造)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
Factory Method Pattern(Another Name: Virtual Constructor)
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

概述:当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用工厂方法模式来设计系统。工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类的实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。

一个实例:假设有三个笔芯,分别是红笔芯、蓝笔芯和黑笔芯。用户希望通过圆珠笔来明确笔芯的颜色

模式的结构中包括四种角色
抽象产品(Product)
具体产品(ConcreteProduct)
构造者(Creator)
具体构造者(ConcreteCreator)

3.png

1.抽象产品(Product) : PenCore.java

public abstract class PenCore{
   String color;
   public abstract void writeWord(String s);
}

2.具体产品(ConcreteProduct)_1 : RedPenCore.java

public class RedPenCore extends PenCore{
    RedPenCore(){
      color="红色";
    }
    public void writeWord(String s){
       System.out.println("写出"+color+"的字:"+s);
    }
}

2.具体产品(ConcreteProduct)_2 : BluePenCore.java

public class BluePenCore extends PenCore{
    BluePenCore(){
      color="蓝色";
    }
    public void writeWord(String s){
       System.out.println("写出"+color+"的字:"+s);
    }
}

2.具体产品(ConcreteProduct)_3: BlackPenCore.java

public class BlackPenCore extends PenCore{
    BlackPenCore(){
      color="黑色";
    }
    public void writeWord(String s){
       System.out.println("写出"+color+"的字:"+s);
    }
}

3.构造者(Creator):BallPen.java

public abstract class BallPen{
    BallPen(){
       System.out.println("生产了一只装有"+getPenCore().color+"笔芯的圆珠笔");
    }
    public abstract PenCore getPenCore(); //工厂方法
}

4.具体构造者(ConcreteCreator):

RedBallPen.java
public class RedBallPen extends BallPen{
    public PenCore getPenCore(){
       return new RedPenCore();
    }
}
BlueBallPen.java
public class BlueBallPen extends BallPen{
    public PenCore getPenCore(){
       return new BluePenCore();
    }
}
BlackBallPen.java
public class BlackBallPen extends BallPen{
    public PenCore getPenCore(){
       return new BlackPenCore();
    }
}

5.应用 Application.java

 public class Application{
    public static void main(String args[]){
       PenCore penCore;
       BallPen ballPen=new BlueBallPen();
       penCore=ballPen.getPenCore();
       penCore.writeWord("你好,很高兴认识你");
       ballPen=new RedBallPen();
       penCore=ballPen.getPenCore();
       penCore.writeWord("How are you");
       ballPen=new BlackBallPen();
       penCore=ballPen.getPenCore();
       penCore.writeWord("nice to meet you");
    }
}

工厂方法模式的优点:

  • 使用工厂方法可以让用户的代码和某个特定类的子类的代码解耦。
  • 工厂方法使用户不必知道它所使用的对象是怎样被创建的,只需知道该对象有哪些方法即可。

一个实例:

  • 创建药品对象:系统设计了一个抽象类Drug,该抽象类特别规定了所创建的药品必须给出药品的成分及其含量。Drug目前有两个子类:Paracetamol和Amorolfine。 Paracetamol子类负责创建氨加黄敏一类的药品, Amorolfine子类负责创建盐酸阿莫罗分一类的药品。
  • 一个为某药店开发的应用程序需要使用Drug类的某个子类的实例为用户提供药品。但是药店的应用程序不能使用Drug的子类的构造方法直接创建对象,因为药店没有能力给出药品的各个成分的含量,只有药厂才有这样的能力。

8.抽象工厂模式

抽象工厂模式(别名:配套)
提供一个创建一系列(相互依赖)对象的接口,而无需指定它们具体的类。
Abstract Factory Pattern(Another Name:Kit)
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

概述:当系统准备为用户提供一系列相关的对象,又不想让用户代码和创建这些对象的类形成耦合时,就可以使用抽象工厂方法模式来设计系统。抽象工厂模式的关键是在一个抽象类或接口中定义若干个抽象方法,这些抽象方法分别返回某个类的实例,该抽象类或接口让其子类或实现该接口的类重写这些抽象方法,为用户提供一系列相关的对象。

一个实例:建立一个系统,该系统可以为用户提供西服套装(上衣+裤子)和牛仔套装(上衣+裤子)。

模式的结构中包括四种角色
抽象产品(Prodcut)
具体产品(ConcreteProduct)
抽象工厂(AbstractFactory)
具体工厂(ConcreteFactory)

1.抽象产品(Product) :

UpperClothes.java
public abstract class UpperClothes{
   public abstract int getChestSize();
   public abstract int getHeight();
   public abstract String getName(); 
}
Trousers.java
public abstract class Trousers{
   public abstract int getWaistSize();
   public abstract int getHeight();
   public abstract String getName(); 
}

2.具体产品(ConcreteProduct)_1: WesternUpperClothes.java

public class WesternUpperClothes extends UpperClothes{
   private int chestSize;
   private int height;
   private String name;
   WesternUpperClothes(String name,int chestSize,int height){
       this.name=name;
       this.chestSize=chestSize;
       this.height=height;
   }
   public int getChestSize(){
       return chestSize;
   }
   public int getHeight(){
       return height;
   }
   public String getName(){
       return name;
   } 
}

2.具体产品(ConcreteProduct)_2: CowboyUpperClothes.java

public class CowboyUpperClothes extends UpperClothes{
   private int chestSize;
   private int height;
   private String name;
   CowboyUpperClothes(String name,int chestSize,int height){
       this.name=name;
       this.chestSize=chestSize;
       this.height=height;
   }
   public int getChestSize(){
       return chestSize;
   }
   public int getHeight(){
       return height;
   }
   public String getName(){
       return name;
   } 
}

2.具体产品(ConcreteProduct)_3: WesternTrousers.java

public class WesternTrousers extends Trousers{
   private int waistSize;
   private int height;
   private String name;
   WesternTrousers(String name,int waistSize,int height){
       this.name=name;
       this.waistSize=waistSize;
       this.height=height;
   }
    public int getWaistSize(){
       return waistSize;
   }
   public int getHeight(){
       return height;
   }
   public String getName(){
       return name;
   } 
}

2.具体产品(ConcreteProduct)_4: CowboyTrousers.java

public class CowboyTrousers extends Trousers{
   private int waistSize;
   private int height;
   private String name;
   CowboyTrousers(String name,int waistSize,int height){
       this.name=name;
       this.waistSize=waistSize;
       this.height=height;
   }
    public int getWaistSize(){
       return waistSize;
   }
   public int getHeight(){
       return height;
   }
   public String getName(){
       return name;
   } 
}

3.抽象工厂(AbstractFactory):ClothesFactory.java

public abstract class ClothesFactory{
    public abstract UpperClothes createUpperClothes(int chestSize,int height);
    public abstract Trousers createTrousers(int waistSize,int height);
}

4.具体工厂(ConcreteFactory):

BeijingClothesFactory.java
public class BeijingClothesFactory extends ClothesFactory {
    public UpperClothes createUpperClothes(int chestSize,int height){
         return new WesternUpperClothes("北京牌西服上衣",chestSize,height);
    }
    public Trousers createTrousers(int waistSize,int height){
         return new WesternTrousers("北京牌西服裤子",waistSize,height);
    }
}
ShanghaiClothesFactory.java
public class ShanghaiClothesFactory extends ClothesFactory {
    public UpperClothes createUpperClothes(int chestSize,int height){
         return new WesternUpperClothes("上海牌牛仔上衣",chestSize,height);
    }
    public Trousers createTrousers(int waistSize,int height){
         return new WesternTrousers("上海牌牛仔裤",waistSize,height);
    }
}

5.应用_1: Shop.java

public class Shop{
    UpperClothes cloth;
    Trousers trouser; 
    public void giveSuit(ClothesFactory factory,int chestSize,int waistSize,int height){
       cloth=factory.createUpperClothes(chestSize,height);
       trouser=factory.createTrousers(waistSize,height);
       showMess();
    }
    private void showMess(){
       System.out.println("<套装信息>");
       System.out.println(cloth.getName()+":");
       System.out.print("胸围:"+cloth.getChestSize());
       System.out.println("身高:"+cloth.getHeight());
       System.out.println(trouser.getName()+":");
       System.out.print("腰围:"+trouser.getWaistSize());
       System.out.println("身高:"+trouser.getHeight());
    }
}

5.应用_2: Application.java

public class Application{
   public static void main(String args[]){
      Shop shop=new Shop();
      ClothesFactory factory=new BeijingClothesFactory(); 
      shop.giveSuit(factory,110,82,170);
      factory=new ShanghaiClothesFactory(); 
      shop.giveSuit(factory,120,88,180);
   }
}

抽象工厂模式的优点:

  • 抽象工厂模式可以为用户创建一系列相关的对象,使得用户和创建这些对象的类脱耦。
  • 使用抽象工厂模式可以方便的为用户配置一系列对象。用户使用不同的具体工厂就能得到一组相关的对象,同时也能避免用户混用不同系列中的对象。
  • 在抽象工厂模式中,可以随时增加“具体工厂”为用户提供一组相关的对象。

一个实例:
军队要为士兵提供机关枪、手枪以及相应的子弹,但军队系统不希望由士兵(用户)来生产机关枪、手枪及相应的子弹,而是应当有专门的的工厂负责配套生产,即有一个专门负责生产机关枪、机关枪子弹的工厂和一个专门负责生产手枪、手枪子弹的工厂。

9.组合模式

组合模式
将对象组合成数形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
Composite Pattern
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

概述:组合模式是关于怎样将对象形成树形结构来表现整体和部分的层次结构的成熟模式。使用组合模式,可以让用户以一致的方式处理个体对象和组合对象,组合模式的关键在于无论是个体对象还是组合对象都实现了相同的接口或都是同一个抽象类的子类。

模式的结构中包括三种角色
抽象组件(Component)
Composite节点(Composite Node)
Leaf节点(Leaf Node)

7.png

1.抽象组件(Component) : MilitaryPerson.java

 import java.util.*;
public interface MilitaryPerson{
      public void add(MilitaryPerson person) ;
      public void remove(MilitaryPerson person) ;
      public MilitaryPerson getChild(int index); 
      public Iterator<MilitaryPerson>  getAllChildren() ;
      public boolean isLeaf();
      public double getSalary();
      public void setSalary(double salary);
  } 

2. Composite节点(Composite Node): MilitaryOfficer.java

import java.util.*;
public class MilitaryOfficer implements MilitaryPerson{
      LinkedList<MilitaryPerson> list;
      String name;
      double salary;
      MilitaryOfficer(String name,double salary){
            this.name=name;
            this.salary=salary;
            list=new LinkedList<MilitaryPerson>();
      } 
      public void add(MilitaryPerson person) {
            list.add(person);
      }
      public void remove(MilitaryPerson person){
            list.remove(person);
      }
      public MilitaryPerson getChild(int index) {
            return list.get(index); 
      }
      public Iterator<MilitaryPerson>  getAllChildren() {
            return list.iterator(); 
      }
      public boolean isLeaf(){
           return false;
      } 
      public double getSalary(){
            return salary;
      }
      public void setSalary(double salary){
           this.salary=salary;
      }
}

3.Leaf节点(Leaf Node):MilitarySoldier.java

import java.util.*;
public class MilitarySoldier implements MilitaryPerson{
      double salary;
      String name;
      MilitarySoldier(String name,double salary){
            this.name=name;
            this.salary=salary;
      }
      public void add(MilitaryPerson person)  {}
      public void remove (MilitaryPerson person){}
      public MilitaryPerson getChild(int index) {
           return null;
      }
      public Iterator<MilitaryPerson>  getAllChildren() {
           return null;
      }
       public boolean isLeaf(){
           return true;
      } 
      public double getSalary(){
           return salary;
      }
      public void setSalary(double salary){
           this.salary=salary;
      }
}

4.应用_1:ComputerSalary.java

import java.util.*;
public class ComputerSalary{
     public static double computerSalary(MilitaryPerson person){
           double sum=0;
           if(person.isLeaf()==true){
                sum=sum+person.getSalary();
           }
           if(person.isLeaf()==false){
                sum=sum+person.getSalary();
                Iterator<MilitaryPerson> iterator=person.getAllChildren();
                while(iterator.hasNext()){
                             MilitaryPerson p= iterator.next();
                             sum=sum+computerSalary(p);;
                }
           }
           return sum;
    }
} 

4.应用_2: Application.java

 public class Application{
      public static void main(String args[]) {
          MilitaryPerson  连长=new MilitaryOfficer("连长",5000);
          MilitaryPerson  排长1=new MilitaryOfficer("一排长",4000); 
          MilitaryPerson  排长2=new MilitaryOfficer("二排长",4000);
          MilitaryPerson  班长11=new MilitaryOfficer("一班长",2000); 
          MilitaryPerson  班长12=new MilitaryOfficer("二班长",2000);
          MilitaryPerson  班长13=new MilitaryOfficer("三班长",2000); 
          MilitaryPerson  班长21=new MilitaryOfficer("一班长",2000); 
          MilitaryPerson  班长22=new MilitaryOfficer("二班长",2000);
          MilitaryPerson  班长23=new MilitaryOfficer("三班长",2000); 
          MilitaryPerson  班长31=new MilitaryOfficer("一班长",2000); 
          MilitaryPerson  班长32=new MilitaryOfficer("二班长",2000);
          MilitaryPerson  班长33=new MilitaryOfficer("三班长",2000); 
          MilitaryPerson  []士兵=new MilitarySoldier[60];
          for(int i=0;i<士兵.length;i++){
                士兵[i]=new MilitarySoldier("小兵",1000);
          }
          连长.add(排长1);             连长.add(排长2);  
          排长1.add(班长11);           排长1.add(班长12);
          排长1.add(班长13);           排长2.add(班长21);  
          排长2.add(班长22);           排长2.add(班长23);
          for(int i=0;i<=9;i++){
                     班长11.add(士兵[i]);                    班长12.add(士兵[i+10]);
                     班长13.add(士兵[i+20]);                 班长21.add(士兵[i+30]);
                     班长22.add(士兵[i+40]);                 班长23.add(士兵[i+50]);
                     班长31.add(士兵[i+60]);                 班长32.add(士兵[i+70]);
                     班长33.add(士兵[i+80]);
          }
          System.out.println("一排的军饷:"+ComputerSalary.computerSalary(排长1));
          System.out.println("一班的军饷:"+ComputerSalary.computerSalary(班长11));
          System.out.println("全连的军饷:"+ComputerSalary.computerSalary(连长));
    }
}

组合模式的优点:

  • 组合模式中包含有个体对象和组合对象,并形成树形结构,使用户可以方便地处理个体对象和组合对象。
  • 组合对象和个体对象实现了相同的接口,用户一般不需区分个体对象和组合对象。
  • 当增加新的Composite节点和Leaf节点时,用户的重要代码不需要作出修改。

10.适配器模式

适配器模式(别名:包装器)
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Adapter Pattern(Another Name: Wrapper)
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

  • 概述:适配器模式是将一个类的接口(被适配者)转换成客户希望的另外一个接口(目标)的成熟模式,该模式中涉及有目标、被适配者和适配器。适配器模式的关键是建立一个适配器,这个适配器实现了目标接口并包含有被适配者的引用。
  • 实例:用户已有一个两相的插座,但最近用户又有了一个新的三相插座。用户现在已经有一台洗衣机和一台电视机,洗衣机按着三相插座的标准配有三相插头,而电视机按着两相插座的标准配有两相插头。现在用户想用新的三相插座来使用洗衣机和电视机。

模式的结构中包括三种角色
目标(Target)
被适配者(Adaptee)
适配器(Adapter)

6.png

1.目标(Target) : ThreeElectricOutlet.java

public interface ThreeElectricOutlet{
    public abstract void connectElectricCurrent(); 
}

2.被适配者(Adaptee): TwoElectricOutlet.java

public interface TwoElectricOutlet{
    public abstract void connectElectricCurrent(); 
 } 

3.适配器(Adapter) TreeElectricAdapter.java

public class TreeElectricAdapter implements ThreeElectricOutlet{
   TwoElectricOutlet outlet;
   TreeElectricAdapter(TwoElectricOutlet outlet){
       this.outlet=outlet;
   }
   public void connectElectricCurrent(){
       outlet.connectElectricCurrent();
   }
}

4.应用 Application.java_1

 public class Application{
    public static void main(String args[]){
       ThreeElectricOutlet outlet;      
       Wash wash=new Wash();            
       outlet=wash;                      
       System.out.println("使用三相插座接通电流:");
       outlet.connectElectricCurrent();   
       TV tv=new TV();                    
       TreeElectricAdapter adapter=new TreeElectricAdapter(tv);
       outlet=adapter;                   
       System.out.println("使用三相插座接通电流:");
       outlet.connectElectricCurrent();   
    }
}

4.应用 Application.java_2

 class Wash implements ThreeElectricOutlet{ 
    String name;
    Wash(){
       name="黄河洗衣机";
    }
    Wash(String s){
       name=s;
    }
    public void connectElectricCurrent(){
       turnOn();
    }
    public void turnOn(){
       System.out.println(name+"开始洗衣物。");
    }
}

4.应用 Application.java_3

 class TV implements TwoElectricOutlet{  
    String name;
    TV(){
       name="长江电视机";
    }
    TV(String s){
       name=s;
    }
    public void connectElectricCurrent(){
       turnOn();
    }
    public void turnOn(){
       System.out.println(name+"开始播放节目。");
    }
}
  • 适配器模式的优点
    目标(Target)和被适配者(Adaptee)是完全解耦的关系。
    适配器模式满足“开-闭原则”。当添加一个实现Adaptee接口的新类时,不必修改Adapter,Adapter就能对这个新类的实例进行适配。

11.外观模式

外观模式
为系统中的一组接口提供一个一致的界面,Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
Chain of Responsibility Pattern
Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.

概述:外观模式是简化用户和子系统进行交互的成熟模式,外观模式的关键是为子系统提供一个称作外观的类,该外观类的实例负责和子系统中类的实例打交道。当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。

应用实例:
邮政系统负责邮寄包裹的子系统包含Check、Weight和Transport类。Check类的实例负责对包裹进行安全检查,Weight类的实例负责根据包裹的重量计算邮资,Transport类的实例负责为包裹选择运输工具。一个要邮寄的包裹的用户如果直接和负责邮寄包裹的子系统的类打交道就会非常不方便。

报社的广告系统有三个类CheckWord、Charge和TypeSetting类,各个类的职责如下:CheckWord类负责检查广告内容含有的字符数量;Charge类的实例负责计算费用;TypeSetting的实例负责对广告进行排版。使用外观模式简化用户和上述子系统所进行的交互。

模式的结构中包括两种角色

  • 子系统(Subsystem)
  • 外观(Facade)
2.png

1.子系统(Subsystem)_1 : CheckWord.java

public class CheckWord{
    public final int basicAmount=85;
    String advertisement;
    int amount;
    public CheckWord(String advertisement){
       this.advertisement=advertisement;
    }
    public void setChargeAmount(){  
       amount=advertisement.length()+basicAmount; //计算出计费字符数目
    } 
    public int getAmount(){
       return amount;
    }
}

1.子系统(Subsystem)_2 : Charge.java

public class Charge{
    public final int basicCharge=12;
    CheckWord checkWord;
    Charge(CheckWord checkWord){
       this.checkWord=checkWord;
    }
    public void giveCharge(){
        int charge=checkWord.getAmount()*basicCharge;
        System.out.println("广告费用:"+charge+"元");
    } 
}

1.子系统(Subsystem)_3 :TypeSeting.java

public class TypeSeting{
    String advertisement;
    public TypeSeting(String advertisement){
       this.advertisement=advertisement;
    }
    public void typeSeting(){ 
       System.out.println("广告排版格式:");
       System.out.println("********");
       System.out.println(advertisement);
       System.out.println("********");  
    } 
}

2.外观(Facade): ClientServerFacade.java

public class ClientServerFacade{
    private CheckWord checkWord;
    private Charge charge;
    private TypeSeting typeSeting;
    String advertisement;
    public ClientServerFacade(String advertisement){
       this.advertisement=advertisement;
       checkWord=new CheckWord(advertisement);
       charge=new Charge(checkWord);
       typeSeting=new TypeSeting(advertisement); 
    }
    public void doAdvertisement(){ 
       checkWord.setChargeAmount();
       charge.giveCharge();
       typeSeting.typeSeting();
    } 
}

3.应用 Application.java

 public class Application{
    public static void main(String args[]){
       ClientServerFacade clientFacade;
       String clientAdvertisement="鹿花牌洗衣机,价格2356元,联系电话:1234567";
       clientFacade=new ClientServerFacade(clientAdvertisement);
       clientFacade.doAdvertisement();
   }
}

外观模式的优点:

  • 使客户和子系统中的类无耦合。
  • 外观只是提供了一个更加简洁的界面,并不影响用户直接使用子系统中的类。
  • 子系统中任何类对其方法的内容进行修改,不影响外观的代码。

一个实例 :
设计一个子系统,该子系统有三个类ReadFile、AnalyzeInformation和SaveFile类,各个类的职责如下:
ReadFile类的实例可以读取文本文件
AnalyzeInformation类的实例可以从一个文本中删除用户不需要的内容
SaveFile类的实例能将一个文本保存到文本文件

12.责任链模式

责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
Chain of Responsibility Pattern
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

概述:责任链模式是使用多个对象处理用户请求的成熟模式,责任链模式的关键是将用户的请求分派给许多对象,这些对象被组织成一个责任链,即每个对象含有后继对象的引用,并要求责任链上的每个对象,如果能处理用户的请求,就做出处理,不再将用户的请求传递给责任链上的下一个对象;如果不能处理用户的请求,就必须将用户的请求传递给责任链上的下一个对象。

实例:用户提交一个人的身份证号码,想知道该人是在北京、上海或者天津居住。

模式的结构中包括两种角色
处理者(Handler)
具体处理者(ConcreteHandler)

1.png

1.处理者(Handler): Handler.java

public interface Handler{
   public abstract void handleRequest(String number);
   public abstract void setNextHandler(Handler handler);
}

2.具体处理者(ConcreteHandler)_1: Beijing.java

import java.util.*;
public class Beijing implements Handler{
     private Handler handler;    
     private ArrayList<String> numberList; 
     Beijing(){
        numberList=new ArrayList<String>();
        numberList.add("11129812340930034"); 
        numberList.add("10120810340930632");
        numberList.add("22029812340930034"); 
        numberList.add("32620810340930632");
     }
     public void handleRequest(String number){
        if(numberList.contains(number))
           System.out.println("该人在北京居住");
        else{
           System.out.println("该人不在北京居住");
           if(handler!=null)
             handler.handleRequest(number);    
        }
     }
     public void setNextHandler(Handler handler){
        this.handler=handler;
     }
}

2.具体处理者(ConcreteHandler)_2: Shanghai.java

import java.util.*;
public class Shanghai implements Handler{
     private Handler handler;            
     private ArrayList<String> numberList; 
     Shanghai(){
        numberList=new ArrayList<String>();
        numberList.add("34529812340930034"); 
        numberList.add("98720810340430632");
        numberList.add("36529812340930034"); 
        numberList.add("77720810340930632");
     }
     public void handleRequest(String number){
        if(numberList.contains(number))
           System.out.println("该人在上海居住");
        else{
           System.out.println("该人不在上海居住");
           if(handler!=null)
              handler.handleRequest(number);     
        }
     }
     public void setNextHandler(Handler handler){
        this.handler=handler;
     }
}

2.具体处理者(ConcreteHandler)_3: Tianjin.java

import java.util.*;
public class Tianjin implements Handler{
     private Handler handler;             
     private ArrayList<String> numberList;  
     Tianjin(){
        numberList=new ArrayList<String>();
        numberList.add("10029812340930034"); 
        numberList.add("20020810340430632");
        numberList.add("30029812340930034"); 
        numberList.add("50020810340930632");
     }
     public void handleRequest(String number){
        if(numberList.contains(number))
           System.out.println("该人在天津居住");
        else{
           System.out.println("该人不在天津居住");
           if(handler!=null)
              handler.handleRequest(number);      
        }
     }
     public void setNextHandler(Handler handler){
        this.handler=handler;
     }
}

3.应用 Application.java

 public class Application{
    private Handler beijing,shanghai,tianjin;   
    public void createChain(){       
       beijing=new Beijing();
       shanghai=new Shanghai();
       tianjin=new Tianjin();
       beijing.setNextHandler(shanghai);
       shanghai.setNextHandler(tianjin);
    }
    public void reponseClient(String number){  
       beijing.handleRequest(number);
    }
    public static void main(String args[]){
       Application  application=new  Application();
       application.createChain();
       application.reponseClient("77720810340930632");;
    }
}

责任链模式的优点:

  • 责任链中的对象只和自己的后继是低耦合关系,和其他对象毫无关联,这使得编写处理者对象以及创建责任链变得非常容易。
  • 使用责任链的用户不必知道处理者的信息,用户不会知道到底是哪个对象处理了它的请求。

应用举例 :

  • 设计一个类,该类创建的对象用int型数据计算阶乘,特点是占用内存小,计算速度快;
  • 设计一个类,该类创建的对象用long型数据计算阶乘,特点是能计算更大整数的阶乘;
  • 设计一个类,该类创建的对象用BigInteger型数据计算阶乘,特点是能计算任意大整数的阶乘;
    要求用责任链模式将上面的对象组成一个责任链,要求责任链上对象的顺序是:首先使用int型数据计算阶乘的对象,然后是使用long型数据计算阶乘的对象,最后是使用BigInteger对象计算阶乘对象。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容