简单了解-设计模式

127 阅读16分钟

文章目录

信使

  1. 信使: 类似“复印本”,保存并且显示“真本”的所有信使,这也可能意味着修改 复印本 并不会影响 真本 的信息改变,不过也可能把复印本改变的内容修改至真本上
public Messenger {
    int a;
    int b;
    public Messenger( int a, int b; int c ) {
        this.a = a;
        this.b = b;
    }
    public Messenger( Messenger m ) [       // 提供了复制真本信使的构造函数
        this.a = m.a;
        this.b = m.b;
    }
}

集合型参数

  1. 集合型参数: 类似“蜜蜂”到处进行采蜂蜜(信使,真本的信息)
class CollectionParameter extends ArrayList {}

public Messager {
    int a;
    int b;
    public Messager( int a, int b ) {
        ths.a = a;
        this.b = b;
    }
    public add( Collection c ) {               // 提供 容器类进行收集数据的接口
        c.add(a);
        c.add(b);
    }
}

CollectionParameter cp = new CollectionParameter();
Messager m = new Messager(1,2);
m.add( cp );     //这里的实参就是集合型参数,不断收集数据

单件

单件: *即某个类只能有一个该类对象,唯一的一个(私有构造函数,类内已经存储一个自身的静态类对象,通过静态方法返回该类对象) *—— 防止其他人自行构建对象,仅能用该类创建者提供的对象

public Father {
    String name;
    private static Father f = new Father( "上帝" );    //唯一能用的该类对象,必须静态
    private father( String name ) { this.name = name; }     //直接私有化构造函数防止用户自行构建新的对象
    public static Father getFather() { return f; }  //返回father对象
    public void set( String name ) { f.name = name; }       //修改father对象的值
}

对象池

class EmptyExceptin extends Exception {}      

class ObjectPool {                //对象池类
    ArrayList items = new ArrayList();              // 用数组进行存储对象池元素
    private ObjectPoolItem {    //对象池存储的元素必须转化成该内部类型,增加判断功能
        private boolean isUse;
        Object item;
        ObjectPoolItem(Object item) { this.item = item; }    // 加入对象池的对象转化成对象池元素的构造函数
    }
    public void add(Object item) {          //池元素增加方法:增加前需转化增加的元素
        ObjectPoolItem op = new ObjectPoolItem( item );
        items.add(op);
    }
    public Object get() throws EmptyException{      // 得到对象池 isUse=false 即还没被用的元素,得不到时返回一个空异常,这个异常是由编程者自身造成的。
        for( int i = 0; i < items.size(); i++) {
            if ( items.get(i).isUse == false ) {
                items.get(i).isUse = true;
                return items.get(i);
            }
        }
        throw new EmptyException();
    }
    public void release(Object a) {     //释放元素 即把 指定元素设为isUse=true;
        for( int i = 0; i < items.size(); i++ ) {
            if( items.get(i) == a ) {
                items.get(i).isUse = false;
                return;
            }
        }
        throws new RuntimeException( a + "no found" );
    }
}

策略模式(Strategy) —— 单个方法的变化

  • 处理算法方式的变化,例如:该图片用什么格式保存、或用什么压缩算法进行压缩文件 —— 用不同的方法做同一样事情
  • 处理:接口方法类、实现该接口的类(各种方法处理实现类)、进行压缩”文件“的类(这个类无需继承接口)
interface Process { public void algorithm(Picture picture); }       //接口方法类(接口算法类)
class Process1 implements Process {    // 具体的实际方法(算法)类1
    public void algorithm(Picture picture) {   System.out.printnln("this is algorithm1" );
}
class Process2 implements Process {     //具体的实际方法(算法)类2
    public void algorithm(Picture picture) { System.out.println("this is algorithm2" );
}

public class  CompressedPricture {      // 该类无需继承接口方法类,单纯只是个图片处理过程
    Process p;          // 算法引用
    Picture a;          //图片
    CompressedPricture( Process p, Picture a ) {    // 指定用哪个算法进行图片压缩
        this.p = p;
        this.a = a;
    }
    public void compress() {
        p.algorithm(a);
    }
}

Policy模式:泛化的策略模式(超类)—— 多个方法的变化

一个事情需要分许多的步骤完成,每个步骤又有多种的解决方案,而不是固定一种解决方案

模板方法( Template method )

  • 类内一个私有(或 final)的基类方法
  • 该方法调用基类一系列可重载的方法(一般作为对象的初始化、应用程序的引擎)
  • 例如:Applet java程序组件:只用户自行重载 init()等,而浏览器渲染交给该Applet类初始化,无需用户设立初始化步骤

abstract class Father {
    Father() { templateMethod(); }       // 调用模板方法进行初始化
    private final void templateMethod() {           // 模板方法进行组织用户重载的方法
        customize1();
        customize2();
    }
    abstract  void customize1();        // 这两条是用户要自行重写的方法
    abstract void customize2();
}

封装创建

  • 强制使用一个通用工厂来创建对象,而不允许创建 对象的代码 分散在整个系统
1.简单工厂方法
abstract class Shape {
    public abstract void draw();
    public abstract void erase();
    public static Shape factory(String type) {
        switch(type) {
            "Circle" : return new Circle();
            "Square" : return new Square();
            defalut: throw new RuntimeException();
        }
    }
class Circle extends Shape {}    // 需自行实现抽象Shape 类内抽象方法
class Square extends Shape{}
    

2.动态工厂( Polymorphic factories )
interface Shape {
    void draw();
    void erase();
}
class ShapeFactory {         // 工厂类 只提供静态方法,来动态生成具体形状
       private static Map factories = new HashMap();
       protected abstract Shape create();           //可重载,具体形状的生成代码
       public static  void addFactory( String id, ShapeFactory f ) {}   // 添加参数到 Map factories 中进行记录保存
       public static final Shape createShape(String id) {      // 调用重载的create()生成形状对象
            if( !factories.containsKey( id ) 
                throw new RuntimeException( "没有该图形" );
            return ( (ShapeFactory)factories.get( id ) ).create();
       }
 }
class Square implements Shape {
    public void draw() {}
    public void erase() {}
    static {                    //只要该类一加载,则自动运行有且只运行一次
        ShapeFactory.addFactory( "Circle" , new Factory() )
    }
    private static class Factory extends ShapeFactory {
        protected Shape create() { return new Square() }    //重载create() 
    }
}
class Circle implements Shape {}   // 同理,跟Square类一样

3.抽象工厂( Abstract Factories )
  • 创建工厂的地方,由你来决定如何使用 该工厂对象创建的那些对象
  • 客户端程序只需要创建抽象工厂的具体实现,而这个抽象工厂的具体小对象已经内部实现好了怎么实现已经封装好了无需客户端用户知道,只要调用 抽象工厂返回小对象的方法 即可
  • 例子: 实现不同用户图形界面的可移植性
interface Obstacle { void action(); }               //做的事情接口    —— 小对象接口类
interface Player { void interactWith( Obstacle ob ); }  // 玩家接口 —— 小对象接口类
interface GameElementFactory {          //玩家与做的事情组合接口 —— 抽象工厂的接口类( 由用户自行组织小对象具体实现类 )
    Player makePlayer();
    Obstacle makeObstacle();
}
class Puzzle implements Obstacle {          //疑问
    public void action() {
        System.out.println("Puzzle");
    }
}
class NastyWeapon implements Obstacle {     //武器
    public void action() {
        System.out.println("NastyWeapon");
    }
}
class Kitty implements Player {             //小猫
    public void interactWith(Obstacle ob) {
        System.out.print("Kity ");
        ob.action();
    }
}
class KungFuGuy implements Player {         //功夫男
    public void interactWith( Obstacle ob ) {
        System.out.println("KungFuGuy ");
        ob.action();
    }
}
class KittyAndPuzzle implements GameElementFactory {        //小猫与疑问
    public Player makePlayer() { return new Kitty(); }
    public Obstacle makeObstacle() { return new Puzzle(); }
}
class GuyAndDismember implements GameElementFactory {       //功夫男与武器
    public Player makePlayer() { return new KungFuGuy(); }
    public Obstacle makeObstacle() { return new NastyWeapon(); }
}

class GameEnvironment {                     // 进行阅读游戏模式  由 GameElementFactory进行得知,是什么模式
    private GameElementFactory gef;
    private Player p;
    private Obstacle ob;
    GameEnvironment( GameElementFactory gef) { 
        this.gef = gef;
        p = gef.makePlayer();
        ob = gef.makeObstacle();
    }
    public void play() {
        p.interactWith(ob);
    }
}

特化创建( Specialized Creation )

1.原型模式( Prototype ) —— 模型重构的那一章节在删除这段话

克隆某个原型的实例来创建对象

2.生成器( Builder )
  • 目的: 对象的构造 与 它的表示 分离开来 → 对象就可以有多个不同的表示
  • 用多个步骤( 对于生成器对象都是外部的 )来创建对象 ——  一步步的创建对象
class Media extends ArrayList
class BooK extends Media
class Magazine extends Media
class Website extends Media

class MediaItem {
    private String s;
    MediaItem(String s) { this.s = s; }
    public String toString() { return s; }
}
class Chapter extends MediaItem {   }
class Article extends MediaItem {     }
class WebItem extends MediaItem {       //前面两个类跟这个是一样的自行补充
    WebItem(String s) { super(s); }
}

class MediaBuilder {
    public void buildBase() {}
    public void addMediaItem( MediaItem item ) {}
    public Media getFinishedMedia() { return null; }
}
class BookBuilder extends MediaBuilder {   }
class MagazineBuilder extends MediaBuilder {    }
class WebsiteBuilder extends  MediaBuilder {            // 上面两个类跟这个类似
    private Website w;
    public void buildBase() { 
        System.out.println("Building magazine frameWork");
        w = new Website();
    }
    public void addMediaItem( MediaItem webItem ) {             //一步步的进行构建对象
        System.out.println("Adding web item" + webItem);
        w.add( webItem );
    }
    public Media getFinishedMedia() { return w; }       //返回最终的构建对象
}

class MediaDirector {                       //状态模式,完成对Builder的生成操作,有无这个类都无所谓
    private MediaBuilder mb;
    public MediaDirector( MediaBuilder mb ) { this.mb = mb; }
    public  Media produceMedia( List input ) {
        mb.buildBase();
        for(int i = 0; i < input.size(); i++) {
            mb.addmediaItem( input.get(i) );
        }
        return mb.getFinishedMedia();
    }
}        

太多( Too Many )

1.享元模式( FlyWeight ) —— 太多对象 ↓
  • 外部化对象数据
  • 在其他模式下,改善性能
class A {
    int a;
    public void set(int a) { this.a = a; }
}      

class B {           // 外部化A里面的数据
    public static int[] number = new int[100];
}
class C {           // 由一个C类来共享B的静态数据
    pubilc int getA( int index ) { return B.number[index]; }
    public void setA( int index, int value ) { B.number[index] = value; }
}

A[] a = new A[100];    // 这里需要运行时新建100个A对象,严重减缓了运行速度
int[] a = B.number;     // 这里只需要B类的数据,以及一个C类数据进行修改B对象的数据 、 只需要运行创建一个对象
2.装饰模式( Decorator ) —— 太多类 ↓
  • 分层的对象 动态地和透明地 给单个对象添加功能
  • 所有外覆在 原始对象 上的装饰类都必须有 同样的基本接口
  • 适用:非常规的继承结构

坏处:代码变得复杂

interface DrinkComponent { 
    String getDescription();
    float getTotalCost();
}

abstract class Decorator implements DrinkComponent {
    protected DrinkComponent dc;
    Decorator(DrinkComponent dc) { this.dc = dc; }
    public String getDescription() { return dc.getDescription(); }
    public float getTotalCost() { return dc.getTotalCost(); }
}

class Mug implements DrinkComponent {
    public String getDescription() { return "Mug"; }
    public float getTotalCost() { return 0; }
}


class Chocolate extends Decorator {
    private float cost = 0.25f;
    private tring description = " chocolate";
    Chocolate(DrinkCompontent dc) { super(dc); }
    public String getDescription() { return dc.getDescription + description; }
    public flaot getTotalCost() { return cost + dc.getTotalCost(); }
}

class Whipped extends Decorator {
    private float cost = 0.25f;
    private String description = " whipped cream";
    Whipped(DrinkComponent dc) { super(dc); }
    public String getDescription() { return dc.getDescription() + desccription; }
    public float getTotalCost() { return dc.getTotalCost() + cost; }
}

DrinkComponent dc = new Whipped( new Chocolate( new Mug() ) ); 
//output: Mug chocolate whipped cream

这种设计类似 自助奶茶 自己调配所有的配料,从头做起,实在是太过麻烦

3.折衷( Compromise )
  • ①预先调制出大部分客户需要的基本成品
  • *②在根据客户的需要在①的基础上添加调料
interface DrinkComponent { 
    float getTotalCost();
    String  getDescription(); 
}

class Cuppuccino implements DrinkComponent {
    private float cost = 1f;
    private String Description = "Cappuccino";
    public String getDescription() { return description; }
    public float getTotalCost() { return cost; }
}

class CofeLatte implements DrinkComponent { 
    private float cost = 1f;
    privaet String Description = "cafe Latte";
    public String getDescription() { return description; }
    public float getTotalCost() { return cost; }
}

abstract class Decorator implements DrinkComponent {
    protected DrinkComponent dc;
    Decorator(DrinkComponent dc) { this.dc = dc; }
    public String getDescription() { return dc.getDescription(); }
    public float getTotalCost() { return dc.getTotalCost(); }
}

class Wet extends Decorator {
    Wet(DrinkComponent dc) { super(dc); }
    public String getDescroption() { return dc.getDescription + " extra steamed milk";
}

class Wet extends Decorator {
    Wet(DrinkComponent dc) { super(dc); }
    public String getDescroption() { return dc.getDescription + " extra foamed milk";
}

DrinkComponent dc = new Wet( new Cappuccino() );
// output: cuppuccino extra steamed milk

这种折衷的组更像 奶茶店 把常用的奶制品已经调好,如果顾客有特殊需求则添加调料即可

连接不同的类型

1.适配器( Adapter )
  • 应用:当你有某个类,而此时 系统/客户 需要另外的类

  • 三种形式

    • ① 代理适配器
    • ② 全继承
    • ③ 内部类适配器
interface WhatIwant {
    void request(); 
}

class WhatIHave {
    void f() {}
    void g() {}
}

//第一种: 代理适配类
class SurrogaeAdapter implements WhatIWant {
    WhatIHave wh;
    SurrogateAdapter( WhatIHave wh ) { this.wh = wh; }
    public void request() {
        wh.f();
        wh.g();
    }
}

//第二种:全继承
class Adapter extends WhatIHave implements WhatIWant {
    public void request() {
        f();
        g();
    }
}

//第三种:内部类适配器

class WhatIHave2 extends WhatIHave {
    private class InnerAdapter implements WhatIWant {
        public void request() {
            f();
            g();
        }
    }
    
    public WhatIWant getAdapter() { return new InnerAdapter(); }
}
2.桥接( Bridge )
  • 结构化代码:容易添加新类型的前端(“抽象类”)、功能由后端类实现(前端类的子类) → 前端,后端互不干扰,分离
  • 前端类:可以拥有完全不一样的接口、通过任意数量的后端对象实现功能
  • 后端类:接口也可以不一样,都是实现某种类似的功能
interface Implementor {     //后端的抽象对象 - 侧面表明不需要在该类有具体的方法
    void facility1();
    void facility2();
    void facility3();
}
class Abstraction {    //前端类
    Implementor ip;
    Abstractor( Implementor ip ) { this.ip = ip; }
    void service1() { 
        ip.facility1();
         ip.facility2();
    }
    void service2() {
        ip.facility2();
        ip.facility3();
    }
    void service3() {
        ip.facility1();
        ip.facility2();
        ip.facility3();
    }
}

class Client1 extends Abstraction {     //根据用户自身需求自行配置,搭配前端接口方法的使用  --- 故有许多个客户定制使用
    public void serviceA() {
        service1();
        service2();
     }
     public void serviceB() {
        service2();
        service3();
     }
     
}
 
class Implementation1 implements Implementor {   // 后端类的方法具体实现子类
    public void facility1() { System.out.println("Implementation1.Facility1()");
    public void facility2() { System.out.println("Implementation1.Facility2()");
    public void facility2() { System.out.println("Implementation1.Facility3()");
}

class Implementation1 implements Implementor {  // 后端类的方法具体实现子类
    public void facility1() { System.out.println("Implementation2.Facility1()");
    public void facility2() { System.out.println("Implementation2.Facility2()");
    public void facility2() { System.out.println("Implementation2.Facility3()");
}

灵活的结构

1.组合模式( Composite )
  • 将整个类结构表现为 树形结构 → 整体/部分
abstract OrganizationComponent {     // 相当于 顶层根节点 Root
    publc void add(OrganizationComponent oc) { throw new UnsupportedOperationException(); }
    public String getName() { throw new UnsupportedOperationException(); }
    public void print() { throw new UnsupportedOperationException(); }
}

class University extends OrganizationComponent {        // 相当于 第二层单节点 Node
    String name;
    List<OrganizationComponent> colleges = new ArrayList<OrganizationComponent>();
    University(String name) { this.name = name; }
    public void add(OrganizationComponent oc) { universities.add(oc); }
    public String getName() { return name; }
    public void print() {
        System.out.println( "-- " + getName + " --" );
        for(OrganizationComponent oc : colleges) {
            oc.print();
         }
     }
 }
 
 class College extends OrganizationComponent {      // 相当于 第三层单节点Node
    String name;
    List<OrganizationComponent>  professionals = new Arraylist<OrganizationComponent>();
    College( String name ) { this.name = name; }
    public void add(OganizationComponent oc) { professionals.add(oc); }
    public String getName() { return name; }
    public void print() {
        System.out.println( "  -- " + getName()  );
        for( OrganizationComponent oc  : professionals ) {
            oc.print();
        }
    }
}

class Professional extends OrganizationComponent {    //相当于 最后一层的叶子节点Leaf
    String name;
    Professional(String name) { this.name = name; }
    public String getName() { return name; }
    public void print() { System.out.println(getName()); }
}

系统解耦( System decoupling )

1.观察者模式( Observer ) —— 订阅模式
  • 允许通过挂钩程序( hook point ) 改变代码完全动态(根据其他对象状态的变化改变自身状态

  • 应用:

    1. 事件管理系统的基本组成部分、完全动态分离呼叫源、被呼叫源代码
    2. 报纸订阅:订报的人(观察者)、报社(被观察者)
    3. 中国好声音:评委(观察者)、歌手(被观察者)
  • 具体:(jdk里面的包)

    1. Observer: 观察者接口
    2. Observable: 被观察者类
  1. 使用内部类
class Singer {    // 被观察者
     String name;
     private boolean isStart = true;   // 两者进行控制
     private boolean isEnd = false;
     Notify notify = new Notify();
     Singer(String name) {
           this.name = name;
     }
     public void sing() {        
           if(isStart && !isEnd) {
               println("\n" + "开始唱歌");
                notify.notifyObservers();
                isStart = false;
                isEnd = true;
           }
     }
     public void endSing() {
           if(!isStart && isEnd) {
                println("\n" + "结束唱歌");
                notify.notifyObservers();
                isEnd = false;
                isStart = true;
           }
     }
     public void addAudience(Observer o) {
           notify.addObserver(o);
     }
     private class Notify extends Observable {
           @Override
           public void notifyObservers() {                
               setChanged();        // 通知所有的观察者时切记必须调用这个方法,而且该方法时“protected"修饰的,只能Observable的继承类来调用。
               super.notifyObservers(isStart);
           }
     }
}
class Audience {            //观察者
     private String name;
     private Notify notify = new Notify();
     Audience(String name) {
           this.name = name;
     }
     public Observer getNotify() {
           return notify;
     }
     private class Notify implements Observer{
           public void update(Observable o, Object args) {  // args时状态值,由NotifObservers(args)中的args传进来的
                int number;
                if((boolean)args == true) {
                     number = 1;
                }else 
                     number = 0;
                switch(number) {
                     case 1: println(name + "听到了歌声,并热烈鼓掌!" );break;
                     case 0: println(name + "歌声结束,并鼓掌!" );break;
                     defaultbreak;
                }               
           }
     }
}

 
2. 不使用内部类、直接继承

class Singer extends Observable {            // 被观察者
   private static final int EXIT_NUMBER  = 0;
   private static final int PERFORM_GOOD = 1;
   private static final int PREFORM_BAD = 2;
    public void perform() {
        int performRandom = new Random(47).nextInt(2) + 1;
        setChanged();
        notifyObservers( performRandom );
    }
    
    public void performEnd() {
        setChanged();
        notifyObservers ( EXIT_NUMBER  );
    }
}

class Audience implements Observer {        // 观察者 
    int  noSeat;
    Audience(int noSeat) { this.noSeat = noSeat; }
    public void update(Observable o, Object args) {
        switch( (int)args ) {
            case 0 : println( noSeat + "号观众离场" ); break;
            case 1 : println( noSeat + "号观众热烈鼓掌" ); break;
            case 2 : println( noSeat + "号观众嘘嘘声" ); break;
        }
    }
}
2.中介者( Mediator )

 

降低接口复杂度

1.外观模式( Facade )—— 门面模式
  • 客户端程序员进行多个类交互较麻烦,把各种类的功能进行包装组成一个大功能 —— 很像代理

  • 举例:

    1. 电脑启动:只需要按主机电源键即可、而无需关心主机内部各住哟啊零件的启动
    2. 茶馆喝茶:只需要叫服务器沏某种茶、而无需关心各种沏茶流程的细节

 

class Computer {                        // 用户只需用这个对象启动电脑即开,调用其start() 会自动的与其他细小的子系统进行交互,而无需用户关心子系统的细节 —— 即门面facade
    Cpu cpu = new Cpu();
    Memory memory = new Memory();
    public void start() {
        cpu.start();
        memory.start();
    }
}

class Cpu {             // 子系统
    public void start() {
        println("Cpu启动");
    }
}

class Memory {          // 子系统
    public void start() {
        println("Memory启动");
    }
}

 

算法分解

1.命令模式( Command ) — 运行时刻选择操作
  • 函数对象: 只为封装一个函数而构造的对象 —— 类似信使( 传值 ),不过函数对象( 传行为 )
  • 特点: 不同的命令做不同的事情,隐藏接收者的执行细节
  • 例子:菜单下的各种命令(复制,粘贴, 移动等)
interface Command { public void execute(); }       // 函数对象接口
class Cook implements Command {
    public void execute() { println(" I am cooking "); }        // 具有行为意义的函数对象类
}
class Run implements Command { 
    public void execute() { println(" I am running "); }    //  具有行为意义的函数对象类
}

class ActionReceiver {       //动作接受者类
    List<Command> commands = new List();     //实质这个容器才是进行收集 行为对象
    public void add(Command command) { commands.add( command ); }       // 添加行为对象
    public void execute() {             // 集中处理所有行为对象的行为
        for( Command c : commands ) 
            c.execute();
    }
}
2.职责链模式( Chain of responsibility ) —— 策略链
  • 策略模式的延申: 依次调用链表里面的每个策略直到 某个策略满足要求 或者 链表执行完都没有符合的策略 才停止
interface  Algorithm {           // 策略接口
     int method(int number);
}

class Add implements Algorithm {            // 具体的策略
     public int method(int number) {
           return number + 5;
     }
}

class Multiplication implements Algorithm {          // 具体的策略
     public int method(int number) {
           return number * 2;
     }
}

class BigNumber {               //  类似搜索系统从各种网站中得到 某种符合标量的信息
     private static int number = 0;
     private static Algorithm[] algorithms = { new Add(), new 
Multiplication() };
     public static void setNumber(int num) { number = num; }
     public static int solve() {                // 从策略数组中一个个试,直到符合条件
           int changed;
           for(Algorithm al : algorithms) {
                changed = al.method(number);
                if(changed > 10)            // 转化符合该条件就退出策略数组,返回策略后的结果
                     return changed;
           }
           throw new RuntimeException(number + " 这个数字没有合适的方法转化为大  数");           // 无策略符合就 抛出异常
     }
}

//测试
public static void main(String[] args) {
    BigNumber.setNumber  = 4;
    try { 
            println( BigNumber.solve() );
    }catch ( Exception e ) {
            prinltln( e.getMessage() );
    }
}

 

外部化对象状态( Externalizing object state )

1.备忘录模式( Memento )

复杂的交互( Complex interactons )

1.多重分派( Multiple dispatching )
  • 利用多态中的动态绑定 → 确定双方的确切实际类型 → 需要两次的动态调用
  • 例子: 加减乘除运算,必须确定两者是哪种确切的数字
class Outcome {      // 用于表示 石头剪刀布 之后的结果对象
    String name; 
    public static final Outcome WIN  = new Outcome("赢"), LOSE = new Outcome("输"), DRAW = new Outcome("平");
    private Outcome( String name ) { this.name = name; }
    public String toString() { return name; }
}

interface Content {
    Outcome compete( Content con );
    Outcome eval( Rock rock );
    Outcome eval( Scissor scissor );
    Outcome eval( Paper paper );
}

class Rock implements Content { 
    public Outcome compete( Content con ) {
        con.eval(this);
    }
    public Outcome eval( Rock rock ) { return Outcome.DRAW; }
    public Outcome eval( Scissor scissor ) { return Outcome.LOSE; }
    public Outcome eval( Paper paper ) { return Outcome.WIN; }
}
class Scissor implements Content {}
class Paper implements Content {}

// 解释
Conten con1 = new Rock();
Contnet con2 = new Scissor();
con1.compete( con2 );      // 当调用该语句时时,能动态的确定  con1是 Rock 类型
                                    // 在运行该函数内部主体是  con2.eval( Rock ) 该函数调用又 动态的确定了 con2是 Scissor 类型
2.访问者模式( Visitor ) —— 多重分派中的一种
  • 特点: 原有的类体系结构不能改变

  • 解决方案:

    1. 假设该体系是双重分派,开始是确定固定不能更能代码的类体系身份
    2. 重新继承创建一个以 参数类为基础 类体系结构
//  前三行的代码 不能修改
interface Flower { public void accept( Visitor v ); }
class Rose implements Flower {   public void accept( Visitor v ) {  v.visit(this); } }
class Lotu implements Flower { public void accept( Visitor v ) {  v.visit(this); } }

// 这个接口的体系可以改变
interface Visitor {   
    public void visit( Rose rose );
    public void visit( Lotu lotu );
}
class Bee implements Visitor {    // 增加新的Visitor 具体类
    public void visit( Rose rose ) { println( " Bee and Rose " ); }
    public void visit( Lotu lotu ) { println( " Bee and Llotu " ) ; }
}
class FlowerName implements Visitor { 
    String flowerName;
    public void visit( Rose rose ) { flowerName = "Rose"; }
    public void visit( Lotu lotu ) { flowerName = "Lotu"; }
    public String toString() { return flowerName; }
}

//运行
Flower[2] flowers = { new Rose(), new Lotu() };
Bee bee = new Bee();
FlowerName fn = new FlowerName();
for( Flower flower : flowers ) {
    flower.accept( bee );               // 该调用直接的打印出 蜜蜂与某种花 活动
    flower.accept( fn );                // 该调用直接修改了  fn的 flowerName变量值
    println( fn );                          // 打印输出 flowerName变量值
}

多个编程语言

翻译模式( Interpreter )