zoukankan      html  css  js  c++  java
  • 设计模式 重点版(常用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();
            }
        }
    
    
    
    
    
  • 相关阅读:
    oracle取字符串长度的函数length()和hengthb()
    kafka优化–JVM参数配置优化
    Linux 查看CPU信息,机器型号,内存等信息
    elasticsearch入库错误:gc overhead导致数据节点脱离集群
    揭密新一代运维管理平台建设七种利器
    EM12C 安装及卸载 注意点整理
    Tools:downloading and Building EDK II工具篇:安装/使用EDKII源代码获取/编译工具[2.3]
    【C语言探索之旅】 第二部分第十课:练习题和习作
    CSDN code使用教程之git使用方法具体解释
    [javase学习笔记]-7.5 构造函数须要注意的几个细节
  • 原文地址:https://www.cnblogs.com/moveofgod/p/4078730.html
Copyright © 2011-2022 走看看