设计模式 重点版(常用10个)

创建型(创建对象): 2 个 (工厂模式, 单例模式)

结构型: 6 个 (适配器模式, 组合模式, 装饰者模式, 代理模式, 外观模式, 桥梁模式)

行为型: 8 个 (中介者模式, 策略模式, 模板模式, 观察者模式, 迭代器模式, 责任链模式, 命令模式, 状态模式)

1. 工厂模式

提供一个创建类的统一接口.

目的: 每次创建类时, 只需要调用这个接口就可以了, 不用每次都需要写一次创建代码

 

上面是简单的工厂模式, 正常的工厂方法模式, 就是针对每个类, 都要创建一个工厂类. 但是他们可以实现共同的接口. (这种模式映射了之前我看的object c 的那本书), 一般用简单的工厂模式就可以了.

2. 单例模式

保证在内存中一个类只有一个实例存在, 并且提供一个访问该实例的全局访问点.

目的: 例如一个系统中可能存在多个打印任务, 但是只能一个正在工作的打印任务在内存中.

 

饿汉式: 类加载时, 就创建好了这个单例( 很饿, 所以要立刻吃, 立刻加载)

懒加载(懒汉式):  可以用的时候再加载 (吃的时候再说, 不是一开始就把饭做好)

如果 getInstance() 使用频率很高, 那肯定是饿汉式好.

 

 

利用 反射 破解单例模式

实际上, 在构造器函数内, 加一句话就可以防止反射破解单例

if (instance != null) {

  throw new RuntimeException();    // 也就是多次多用构造器时, 抛出异常

通过反序列化的方式 构造多个对象, 破解单例

首先,通过序列化把对象写到硬盘上, 然后在把这个对象反序列化读回到程序中, 这时就不是之前的对象了.

如何防止序列化, 通过定义一个 readResolve() 方法 , 这个方法的作用是,在反序列化时, 如果这个类已经定义了实例, 直接返回这个实例就可以了, 不需要new一个新的了.

3. 适配器模式

将一个类的接口转换成客户希望的另一个接口.

目的: 比如我们去别的地方, 我们的插座的方向头是不一样的, 比如(中国, 德国 我出差去德国), 适配器需要满足以下要求:

(1) 必须符合德国标准的接口,否则的话还是没办法插到德国插座中

(2) 在调用上面实现的德标接口进行充电时,提供一种机制,将这个调用转到对国标接口的调用

这就要求:

(1) 适配器必须实现原有的旧的接口

(2) 适配器对象中持有对新接口的引用,当调用旧接口时,将这个调用委托给实现新接口的对象来处理,也就是在适配器对象中组合一个新接口

image

4. 组合模式

将对象组合成树型结构以表示“部分---整体”的层次结构

image

组合模式类似 “树”

component: 组合中对象的接口声明

composite: 树枝结点(有子节点)

leaf: 树叶结点(无子节点)

目的: 就是你想要这种层次关系的类时, 就可以使用.

例如: 各部门之间的层级关系

抽象接口类:
 
package com.zyh.designpattern.composite;
 
public abstract class Company {
 
private String name;
 
public Company(String name) {
 
super();
 
this.name = name;
 
}
 
public Company(){}
 
public String getName() {
 
return name;
 
}
 
public void setName(String name) {
 
this.name = name;
 
}
 
protected abstract void add(Company company);
 
protected abstract void romove(Company company);
 
protected abstract void display(int depth);
 
}
 
枝结点类:
 
package com.zyh.designpattern.composite;
 
import java.util.ArrayList;
 
import java.util.List;
 
public class ConcreteCompany extends Company {
 
private List cList; public ConcreteCompany() { cList = new ArrayList(); } public ConcreteCompany(String name) { super(name); cList = new ArrayList(); } @Override
 
protected void add(Company company) {
 
// TODO Auto-generated method stub
 
cList.add(company);
 
}
 
@Override
 
protected void display(int depth) {
 
// TODO Auto-generated method stub
 
StringBuilder sb = new StringBuilder("");
 
for (int i = 0; i < depth; i++) {
 
sb.append("-");
 
}
 
System.out.println(new String(sb) + this.getName());
 
for (Company c : cList) {
 
c.display(depth + 2);
 
}
 
}
 
@Override
 
protected void romove(Company company) {
 
// TODO Auto-generated method stub
 
cList.remove(company);
 
}
 
}
 
两个叶结点类:
 
-------------------------1---------------------------.
 
package com.zyh.designpattern.composite;
 
public class HRDepartment extends Company {
 
public HRDepartment(String name) {
 
super(name);
 
}
 
@Override
 
protected void add(Company company) {
 
}
 
@Override
 
protected void display(int depth) {
 
// TODO Auto-generated method stub
 
StringBuilder sb = new StringBuilder("");
 
for (int i = 0; i < depth; i++) {
 
sb.append("-");
 
}
 
System.out.println(new String(sb) + this.getName());
 
}
 
@Override
 
protected void romove(Company company) {
 
}
 
}
 
----------------2-------------------
 
package com.zyh.designpattern.composite;
 
public class FinanceDepartment extends Company {
 
public FinanceDepartment(String name) {
 
super(name);
 
}
 
@Override
 
protected void add(Company company) {
 
}
 
@Override
 
protected void display(int depth) {
 
// TODO Auto-generated method stub
 
StringBuilder sb = new StringBuilder("");
 
for (int i = 0; i < depth; i++) {
 
sb.append("-");
 
}
 
System.out.println(new String(sb) + this.getName());
 
}
 
@Override
 
protected void romove(Company company) {
 
}
 
}
 
客户端:
 
package com.zyh.designpattern.composite;
 
public class Client {
 
public static void main(String[] args) {
 
// TODO Auto-generated method stub
 
Company root = new ConcreteCompany();
 
root.setName("北京总公司");
 
root.add(new HRDepartment("总公司人力资源部"));
 
root.add(new FinanceDepartment("总公司财务部"));
 
Company shandongCom = new ConcreteCompany("山东分公司");
 
shandongCom.add(new HRDepartment("山东分公司人力资源部"));
 
shandongCom.add(new FinanceDepartment("山东分公司账务部"));
 
Company zaozhuangCom = new ConcreteCompany("枣庄办事处");
 
zaozhuangCom.add(new FinanceDepartment("枣庄办事处财务部"));
 
zaozhuangCom.add(new HRDepartment("枣庄办事处人力资源部"));
 
Company jinanCom = new ConcreteCompany("济南办事处");
 
jinanCom.add(new FinanceDepartment("济南办事处财务部"));
 
jinanCom.add(new HRDepartment("济南办事处人力资源部"));
 
shandongCom.add(jinanCom);
 
shandongCom.add(zaozhuangCom);
 
Company huadongCom = new ConcreteCompany("上海华东分公司");
 
huadongCom.add(new HRDepartment("上海华东分公司人力资源部"));
 
huadongCom.add(new FinanceDepartment("上海华东分公司账务部"));
 
Company hangzhouCom = new ConcreteCompany("杭州办事处");
 
hangzhouCom.add(new FinanceDepartment("杭州办事处财务部"));
 
hangzhouCom.add(new HRDepartment("杭州办事处人力资源部"));
 
Company nanjingCom = new ConcreteCompany("南京办事处");
 
nanjingCom.add(new FinanceDepartment("南京办事处财务部"));
 
nanjingCom.add(new HRDepartment("南京办事处人力资源部"));
 
huadongCom.add(hangzhouCom);
 
huadongCom.add(nanjingCom);
 
root.add(shandongCom);
 
root.add(huadongCom);
 
root.display(0);
 
}
 
}
各部门之间层级关系

5. 装饰者模式

动态的给一个对象添加一些额外的职责

目的: 需要扩展一个类的功能, 或给一个类增加额外的功能, 例如: 比如生日蛋糕, 有一些级别的蛋糕的情况, 比如, 巧克力蛋糕, 草莓蛋糕等, 但是, 要想在蛋糕上单独加一些东西, 比如加一些花, 等等, 这样, 就可以将基本的蛋糕采用继承关系, 而装饰者有个抽象类, 那些加的花啊什么的, 都是继承这个装饰者类, 参考下边类图

image

6. 代理模式

为其他对象提供一种代理以控制对这个对象的访问

目的: 对对象访问进行控制, 比如西门庆找潘金莲,那潘金莲不好意思答复呀,咋办,找那个王婆做代理,表现在程序上时是这样的体现的

代码如下:

package com.yangguangfu.proxy;
/**
 * 
 * @author 阿福(trygf521@126.com)<br>
 *定义一种类型的女人,王婆和潘金莲都属于这个类型的女人
 */
public interface KindWoman {
    
    //这种女人能做什么事情呢?
    public void makeEyesWithMan();//抛媚眼
    
    public void happyWithMan();//和男人那个....

}
一种类型嘛,那肯定是接口,定义个潘金莲
package com.yangguangfu.proxy;
/**
 * 
 * @author 阿福(trygf521@126.com)<br>
 *定义一个潘金莲是什么样的人
 */
public class PanJinLian  implements KindWoman{

    @Override
    public void happyWithMan() {
        System.out.println("潘金莲和男人在做那个...");
        
    }

    @Override
    public void makeEyesWithMan() {
        System.out.println("潘金莲抛媚眼...");
        
    }

}
再定义个丑陋的王婆
package com.yangguangfu.proxy;
/**
 * 
 * @author 阿福(trygf521@126.com)<br>
 *王婆这个人老聪明了,她太老了,是个男人都看不上她,
 *但是她有智慧经验呀,他作为一类女人的代理!
 */
public class WangPo implements KindWoman {
    
    private KindWoman kindWoman;
    
    public WangPo(){
        //默认的话是潘金莲的代理
        this.kindWoman = new PanJinLian();
    }
    //她可以是KindWomam的任何一个女人的代理,只要你是这一类型
    public WangPo(KindWoman kindWoman){
        this.kindWoman = kindWoman;
    }

    @Override
    public void happyWithMan() {
        //自己老了,干不了了,但可以叫年轻的代替。
        this.kindWoman.happyWithMan();
        
    }

    @Override
    public void makeEyesWithMan() {
        //王婆年纪大了,谁看她抛媚眼啊
        this.kindWoman.makeEyesWithMan();
        
    }

}
两个女主角都上场了,该男主角了,定义个西门庆
package com.yangguangfu.proxy;
/**
 * 
 * @author 阿福(trygf521@126.com)<br>
 *水浒传是这样写的:西门庆被潘金莲用竹竿敲了一下,西门庆看痴迷了,被王婆看到了,就开始撮合两人好事,王婆作为潘金莲的代理人收了不少好处费,那我们假设一下:
 *如果没有王婆在中间牵线,这两个不要脸的能成事吗?难说得很!
 */
public class XiMenQiang {

    /**
     * @param args
     */
    public static void main(String[] args) {
        WangPo wangPo;
        //把王婆叫出来
         wangPo = new WangPo();
        //然后西门庆说,我要和潘金莲Happy,然后王婆就安排了西门庆丢筷子哪出戏:
        wangPo.makeEyesWithMan();
        //看到没有表面是王婆在做,其实爽的是潘金莲
        wangPo.happyWithMan();
        
        

    }

}

image

7. 外观模式

为子系统中的一组接口提供一个一致的界面

比如: 不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶、茶具和开水,如图1(A)所示,而去茶馆喝茶,最简单的方式就是跟茶馆服务员说想要一杯什么样的茶,是铁观音、碧螺春还是西湖龙井?正因为茶馆有服务员,顾客无须直接和茶叶、茶具、开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可,整个过程非常简单省事,如图1(B)所示

image

在软件开发中,有时候为了完成一项较为复杂的功能,一个客户类需要和多个业务类交互,而这些需要交互的业务类经常会作为一个整体出现,由于涉及到的类比较多,导致使用时代码较为复杂,此时,特别需要一个类似服务员一样的角色,由它来负责和多个业务类进行交互,而客户类只需与该类交互。外观模式通过引入一个新的外观类(Facade)来实现该功能,外观类充当了软件系统中的“服务员”,它为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。在外观模式中,那些需要交互的业务类被称为子系统(Subsystem)。如果没有外观类,那么每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度将很大,如图2(A)所示;而引入外观类之后,客户类只需要直接与外观类交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,从而降低了系统的耦合度,如图2(B)所示。

image

image

8. 桥梁模式

桥梁模式将抽象部分与它的实现部分分离

image

目的: 比如我们有一个画图程序 有2个图形(Circle Rectangle )和2种画图方法(Drawing1 Drawing2)图形可能会使用Drawing1来画图 也可能使用Drawing2来画图在这个画图程序中有两个可变因素 一个是图形的种类 有可能会增加新的图形 另一个是画图方法 可能会有Drawing3出现.

9. 中介者模式

中介者模式用一个中介对象封装一系列的对象交互

目的: 比如 在生活中,当电脑缺少了一块主板,那会怎么样?如果有人这样问我的话,我就会马上跳出来说“这电脑肯定报废了”,当然这不是重点。假如少了主板电脑还可以用的话,想想,里面的CPU、显卡、声卡、光驱、硬盘等等,不是就要我们自己用线把它们连起来。想想就觉得头疼,那么现在你觉得主板在电脑里扮演着什么角色呢?

例2:

imageimage

image
Mediator:中介者接口。在里面定义了各个同事之间相互交互所需要的方法,可以是公共的方法,如Change方法,也可以是小范围的交互方法

ConcreteMediator:具体的中介者实现对象。它需要了解并为维护每个同事对象,并负责具体的协调各个同事对象的交互关系。

Colleague:同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是每个同事对象都会持有中介者对象的引用,这个功能可定义在这个类中。

ConcreteColleague:具体的同事类,实现自己的业务,需要与其他同事对象交互时,就通知中介对象,中介对象会负责后续的交互。

10. 策略模式

策略模式定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换

比如:

刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开能解决棘手问题,嘿,还别说,真解决了大问题,搞到最后是周瑜陪了夫人又折兵,那咱们先看看这个场景是什么样子的。

先说说这个场景中的要素:三个妙计,一个锦囊,一个赵云,妙计是亮哥给的,妙计放在锦囊里,俗称就是锦囊妙计嘛,那赵云就是一个干活的人,从锦囊取出妙计,执行,然后获胜。用java程序怎么表现这些呢?

那我们先来看看图

image

三个妙计是同一类型的东西,那咱就写个接口:

package com.yangguangfu.strategy;
/**
 * 
 * @author trygf521@126.com:阿福
 * 首先定义一个策略接口,这是诸葛亮老人家给赵云的三个锦囊妙计的接口。
 */
public interface IStrategy {
    //每个锦囊妙计都是一个可执行的算法。
    public void operate();

}

然后再写三个实现类,有三个妙计嘛:

妙计一:初到吴国:

package com.yangguangfu.strategy;
/**
 * 
 * @author trygf521@126.com:阿福
 * 找乔国老帮忙,使孙权不能杀刘备。
 */
public class BackDoor implements IStrategy {

    @Override
    public void operate() {
        System.out.println("找乔国老帮忙,让吴国太给孙权施加压力,使孙权不能杀刘备...");
    }

}

妙计二:求吴国太开个绿灯,放行:

package com.yangguangfu.strategy;
/**
 * 
 * @author trygf521@126.com:阿福
 * 求吴国太开个绿灯。
 */
public class GivenGreenLight implements IStrategy {

    @Override
    public void operate() {
        System.out.println("求吴国太开个绿灯,放行!");
        
    }

}

妙计三:孙夫人断后,挡住追兵:

package com.yangguangfu.strategy;
/**
 * 
 * @author trygf521@126.com:阿福
 * 孙夫人断后,挡住追兵。
 */
public class BlackEnemy implements IStrategy {

    @Override
    public void operate() {
        System.out.println("孙夫人断后,挡住追兵...");

    }

}
好了,大家看看,三个妙计是有了,那需要有个地方放妙计啊,放锦囊里:
package com.yangguangfu.strategy;
/**
 * 
 * @author trygf521@126.com:阿福
 *
 */
public class Context {
    
    private IStrategy strategy;
    //构造函数,要你使用哪个妙计
    public Context(IStrategy strategy){
        this.strategy = strategy;
    }
    
    public void operate(){
        this.strategy.operate();
    }

}
然后就是赵云雄赳赳的揣着三个锦囊,拉着已步入老年行列,还想着娶纯情少女的,色咪咪的刘备老爷子去入赘了,嗨,还别说,亮哥的三个妙计还真不错,瞧瞧:
package com.yangguangfu.strategy;

public class ZhaoYun {

    /**
     * 赵云出场了,他根据诸葛亮给他的交代,依次拆开妙计
     */
    public static void main(String[] args) {
        Context context;
        
        //刚到吴国的时候拆开第一个
        System.out.println("----------刚刚到吴国的时候拆开第一个---------------");
        context = new Context(new BackDoor());
        context.operate();//拆开执行
        System.out.println("












");
        
        //当刘备乐不思蜀时,拆开第二个
        System.out.println("----------刘备乐不思蜀,拆第二个了---------------");
        context = new Context(new GivenGreenLight());
        context.operate();//拆开执行
        System.out.println("












");
        
        //孙权的小追兵了,咋办?拆开第三个锦囊
        System.out.println("----------孙权的小追兵了,咋办?拆开第三个锦囊---------------");
        context = new Context(new BlackEnemy());
        context.operate();//拆开执行
        System.out.println("












");
    }

}
image
imageimage
 

11. 模板模式

定义一个操作中的算法骨架, 而将一些步骤延迟到子类中

个人感觉是定义一套流程”即算法骨架”, 置于骨架的内容, 要到实现时, 会有不同

比如: 我们使用冲泡咖啡和冲泡茶的例子

加工流程:

咖啡冲泡法:1.把水煮沸、2.用沸水冲泡咖啡、3.把咖啡倒进杯子、4.加糖和牛奶

茶冲泡法: 1.把水煮沸、2.用沸水冲泡茶叶、3.把 茶 倒进杯子、4.加蜂蜜

实践步骤:

1>创建一个模板(抽象)类:Beverage(饮料) 这里包含”骨架”

package com.kaishengit.beverage;

public abstract class Beverage {
    /**
     * 冲泡咖啡或茶...流程
     */
    public final void create(){
        boilWater();//把水煮沸
        brew();//用沸水冲泡...
        pourInCup();//把...倒进杯子
        addCoundiments();//加...
    }


    public abstract void addCoundiments();

    public abstract void brew();
    
    public void boilWater() {
        System.out.println("煮开水");
    }
    
    public void pourInCup() {
        System.out.println("倒进杯子");
    }
}

2>创建一个咖啡类(Coffee)和茶(Tea)类,都继承Beverage抽象类

1.咖啡(Coffee)

package com.kaishengit.beverage;

public class Coffee extends Beverage{

    @Override
    public void addCoundiments() {
        System.out.println("添加糖和牛奶");    }

    @Override
    public void brew() {
        System.out.println("用水冲咖啡");
    }
}

2. 茶(Tea)

package com.kaishengit.beverage;

public class Tea extends Beverage{

    @Override
    public void addCoundiments() {
        System.out.println("添加蜂蜜");
    }

    @Override
    public void brew() {
        System.out.println("用水冲茶");
    }

}

image

12. 观察者模式

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象

模式中的角色

  抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

  具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

  抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

  具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调

image

想想自己blog的气象站的例子(headfirst 设计模式中的例子)

13. 迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中各个元素

image

迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口

具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。

Aggregate (聚合): 聚合定义创建相应迭代器对象的接口

ConcreteAggregate (具体聚合): 具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例

比如: 早期电视机, 按电视上按钮换台那种, 当我们换频道时, 重要的不是几频道, 而是节目内容.

在面向对象的软件设计中, 我们经常会遇到一类集合对象, 这类集合对象的内部结构可能有着各种各样的实现, 但是归结起来, 无非有两点是我们关心的: 一是集合内部的数据存储结构, 二是遍历这个集合内部的数据. Iterator 模式就是分离了集合对象的遍历行为.

image

首先有一个抽象的聚集, 所谓聚集就是数据的集合, 可以循环去访问它, 它只有一个方法 GetIterator()让子类去实现, 用来获得一个迭代器对象.

抽象迭代器: Iterator, 它用来访问聚集的类, 封装了一些方法, 通常会有 MoveNext(), CurrentItem(), First(), Next()

具体聚集 ConcreteList: 它实现了抽象聚集中的唯一方法, 同时再里面保存了一组数据

具体迭代器 ConcreteIterator: 具体迭代器, 它实现了迭代器中的4个方法, 在它的构造函数中需要接受一个具体聚集类型的参数.

14. 责任链模式

责任链模式使多个对象都有机会处理请求

image

抽象处理者 Handler: 定义出一个处理请求的接口,如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。

具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

比如: 请假,审批的例子, 在公司里,如果你的请假时间小于0.5天,那么只需要向项目经理打声招呼就OK了, 如果超过了0.5天,但是还小于2天,那么就要去找人事部处理,当然,这就要扣工资了, 如果超过了2天,你就需要去找总经理了,工资当然也玩完了。那么,对于我们来说,这个流程就是这样的。

image

也就是这样一个过程,你需要和你的直接上级——项目经理去打交道,最终可能是项目经理给你回邮件,可能是人事部给你回邮件,也可能是总经理给你回邮件。内部的过程其实应该是个黑盒子,你并不知道内部的消息是如何处理的。你需要找到的,只是你想要第一个交付的对象而已.

下边是一个审批例子的具体代码.

抽象处理者角色

public abstract class Handler {
    /**
     * 持有下一个处理请求的对象
     */
    protected Handler successor = null;
    /**
     * 取值方法
     */
    public Handler getSuccessor() {
        return successor;
    }
    /**
     * 设置下一个处理请求的对象
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    /**
     * 处理聚餐费用的申请
     * @param user    申请人
     * @param fee    申请的钱数
     * @return        成功或失败的具体通知
     */
    public abstract String handleFeeRequest(String user , double fee);

具体处理者角色

项目经理

public class ProjectManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //项目经理权限比较小,只能在500以内
        if(fee < 500)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:项目经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:项目经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //超过500,继续传递给级别更高的人处理
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }

}

部门经理

public class DeptManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //部门经理的权限只能在1000以内
        if(fee < 1000)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:部门经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:部门经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //超过1000,继续传递给级别更高的人处理
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }

}

部长

public class GeneralManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //总经理的权限很大,只要请求到了这里,他都可以处理
        if(fee >= 1000)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:总经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:总经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //如果还有后继的处理对象,继续传递
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }

}

客户端类 (测试)

public class Client {

    public static void main(String[] args) {
        //先要组装责任链
        Handler h1 = new GeneralManager();
        Handler h2 = new DeptManager();
        Handler h3 = new ProjectManager();
        h3.setSuccessor(h2);
        h2.setSuccessor(h1);
        
        //开始测试
        String test1 = h3.handleFeeRequest("张三", 300);
        System.out.println("test1 = " + test1);
        String test2 = h3.handleFeeRequest("李四", 300);
        System.out.println("test2 = " + test2);
        System.out.println("---------------------------------------");
        
        String test3 = h3.handleFeeRequest("张三", 700);
        System.out.println("test3 = " + test3);
        String test4 = h3.handleFeeRequest("李四", 700);
        System.out.println("test4 = " + test4);
        System.out.println("---------------------------------------");
        
        String test5 = h3.handleFeeRequest("张三", 1500);
        System.out.println("test5 = " + test5);
        String test6 = h3.handleFeeRequest("李四", 1500);
        System.out.println("test6 = " + test6);
    }

}

输出结果:

image

15. 命令模式

将一个请求封装成为一个对象, 使可以用不同的请求对客户进行参数化

image

命令角色(Command):声明执行操作的接口。有java接口或者抽象类来实现。

具体命令角色(Concrete Command):将一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现命令角色声明的执行操作的接口

客户角色(Client):创建一个具体命令对象(并可以设定它的接收者

请求者角色(Invoker):调用命令对象执行这个请求

接收者角色(Receiver):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者

比如: 电视机遥控器

电视机是请求的接收者Receiver,遥控器是请求的发送者Invoker, 遥控器上有一些按钮,不同的按钮对应电视机的不同操作Command. 抽象命令角色由一个命令接口来扮演, 有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道

代码如下:
public interface Command {
    public void execute();
}


public class ConcreteCommand implements Command {

    private Receiver receiver = null;
    private String state;

    public ConcreteCommand(Receiver receiver){
       this.receiver = receiver;
    }  
    public void execute() {
       receiver.action();
    }
}


public class Receiver {
    public void action(){
       //真正执行命令操作的功能代码
    }
}


public class Invoker {
    private Command command = null;

    public void setCommand(Command command) {
       this.command = command;
    }

    public void runCommand() {
       command.execute();
    }
}

public class Client {
    public void assemble(){
       //创建接收者
       Receiver receiver = new Receiver();
       //创建命令对象,设定它的接收者
       Command command = new ConcreteCommand(receiver);
       //创建Invoker,把命令对象设置进去
       Invoker invoker = new Invoker();
       invoker.setCommand(command);
    }
}
模拟电视机换台的代码:
下面给个例子,是模拟对电视机的操作有开机、关机、换台命令。代码如下

//命令接收者
public class Tv {
  public int currentChannel = 0;

  public void turnOn() {
     System.out.println("The televisino is on.");
  }

  public void turnOff() {
     System.out.println("The television is off.");
  }

  public void changeChannel(int channel) {
     this.currentChannel = channel;
     System.out.println("Now TV channel is " + channel);
  }
}

//执行命令的接口
public interface Command {
  void execute();
}

//开机命令
public class CommandOn implements Command {
  private Tv myTv;

  public CommandOn(Tv tv) {
     myTv = tv;
  }

  public void execute() {
     myTv.turnOn();
  }
}

//关机命令
public class CommandOff implements Command {
  private Tv myTv;

  public CommandOff(Tv tv) {
     myTv = tv;
  }

  public void execute() {
     myTv.turnOff();
  }
}

//频道切换命令
public class CommandChange implements Command {
  private Tv myTv;

  private int channel;

  public CommandChange(Tv tv, int channel) {
     myTv = tv;
     this.channel = channel;
  }

  public void execute() {
     myTv.changeChannel(channel);
  }
}

//可以看作是遥控器吧
public class Control {
  private Command onCommand, offCommand, changeChannel;

  public Control(Command on, Command off, Command channel) {
     onCommand = on;
     offCommand = off;
     changeChannel = channel;
  }

  public void turnOn() {
     onCommand.execute();
  }

  public void turnOff() {
     offCommand.execute();
  }

  public void changeChannel() {
     changeChannel.execute();
  }
}

//测试类
public class Client {
  public static void main(String[] args) {
     // 命令接收者
     Tv myTv = new Tv();
     // 开机命令
     CommandOn on = new CommandOn(myTv);
     // 关机命令
     CommandOff off = new CommandOff(myTv);
     // 频道切换命令
     CommandChange channel = new CommandChange(myTv, 2);
     // 命令控制对象
     Control control = new Control(on, off, channel);

     // 开机
     control.turnOn();
     // 切换频道
     control.changeChannel();
     // 关机
     control.turnOff();
  }
}


执行结果为:
The televisino is on.
Now TV channel is 2
The television is off.

16. 状态模式

状态模式容许一个对象在其内部状态改变时改变它的行为
image
上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理.
抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为 
具体状态(Concrete State):实现抽象状态定义的接口
举例:
电灯有两个状态,开(亮)与关(不亮),下面就用状态模式来实现对电灯的控制
image
/// <summary>
    /// 电灯类,对应模式中的Context类
    /// </summary>
    public class Light
    {
        private LightState state;

        public Light(LightState state)
        {
            this.state = state;
        }

        /// <summary>
        /// 按下电灯开关
        /// </summary>
        public void PressSwich()
        {
            state.PressSwich(this);
        }

        public LightState State
        {
            get { return state; }
            set { state = value; }
        }    
    }

    /// <summary>
    /// 抽象的电灯状态类,相当于State类
    /// </summary>
    public abstract class LightState
    {
        public abstract void PressSwich(Light light);
    }

    /// <summary>
    /// 具体状态类, 开
    /// </summary>
    public class On : LightState
    {
        /// <summary>
        /// 在开状态下,按下开关则切换到关的状态。
        /// </summary>
        /// <param name="light"></param>
        public override void PressSwich(Light light)
        {
            Console.WriteLine("Turn off the light.");

            light.State = new Off();
        }
    }

    /// <summary>
    /// 具体状态类,关
    /// </summary>
    public class Off: LightState
    {
        /// <summary>
        /// 在关状态下,按下开关则打开电灯。
        /// </summary>
        /// <param name="light"></param>
        public override void PressSwich(Light light)
        {
            Console.WriteLine("Turn on the light.");

            light.State = new On();
        }
    }
客户端代码
class Program
    {
        static void Main(string[] args)
        {
            // 初始化电灯,原始状态为关
            Light light = new Light(new Off());

            // 第一次按下开关,打开电灯
            light.PressSwich();
            // 第二次按下开关,关闭电灯
            light.PressSwich();

            Console.Read();
        }
    }




原文地址:https://www.cnblogs.com/moveofgod/p/4078730.html