首页 > 代码库 > 设计模式 重点版

设计模式 重点版

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

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

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

 

1. 工厂模式

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

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

 

2. 单例模式

保证在内存中一个类只有一个实例存在

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

 

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();//和男人那个....}
<style></style>
一种类型嘛,那肯定是接口,定义个潘金莲
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();            }}
<style></style>
两个女主角都上场了,该男主角了,定义个西门庆
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();                    }}
<style></style><style></style><style></style><style></style>

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();}
<style></style>

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

妙计一:初到吴国:

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("求吴国太开个绿灯,放行!");            }}
<style></style>

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

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("\n\n\n\n\n\n\n\n\n\n\n\n\n");                //当刘备乐不思蜀时,拆开第二个        System.out.println("----------刘备乐不思蜀,拆第二个了---------------");        context = new Context(new GivenGreenLight());        context.operate();//拆开执行        System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n");                //孙权的小追兵了,咋办?拆开第三个锦囊        System.out.println("----------孙权的小追兵了,咋办?拆开第三个锦囊---------------");        context = new Context(new BlackEnemy());        context.operate();//拆开执行        System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n");    }}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("倒进杯子");    }}
<style></style>

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("用水冲咖啡");    }}
<style></style>

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("用水冲茶");    }}
<style></style>

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;    }}
<style></style>

部门经理

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;    }}
<style></style>

部长

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;    }}
<style></style>

客户端类 (测试)

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);    }}
<style></style>

输出结果:

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 2The television is off.
<style></style><style></style><style></style>

 

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();        }    }
<style></style>
客户端代码
class Program    {        static void Main(string[] args)        {            // 初始化电灯,原始状态为关            Light light = new Light(new Off());            // 第一次按下开关,打开电灯            light.PressSwich();            // 第二次按下开关,关闭电灯            light.PressSwich();            Console.Read();        }    }
<style></style>
 
 
<style></style><style></style><style></style>

设计模式 重点版