• 23种设计模式趣谈


    0 阅读注意事项

    里面的趣谈故事部分为套用名著人物的虚构故事。
    选用四大名著角色和故事的原因:
    一是这些都是耳熟能详的角色,希望能在读者脑海里勾出点想象;
    二是为了读者能更好的记住这些小故事,从而帮助理解这23种设计模式。

    不过,故事只是一种让我们记住这些知识的途径,但是体会理解是否正确还是要回归正经的概念。可见此博文:
    23种设计模式解析

    1 工厂方法模式(Factory Method)

    1.1 普通工厂模式

    士兵的种类有步兵和骑兵。
    刘备手下有五千步兵,一千骑兵,都存放在练兵场。
    谁想领兵,得向练兵场负责人递纸条,领步兵的话得写”Infantry“,领骑兵的话得写”Trooper“。

    public interface Soldier{
        void fight();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    public class Infantry implements Soldier{
        @Override
        public void fight() {
            System.out.println("Infantry walk forward!");
        }
    }
    public class Trooper implements Soldier{
    
        @Override
        public void fight() {
            System.out.println("Trooper horse riding!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class Principal{
    
        public Soldier produce(String type) {
            if ("Infantry".equals(type)) {
                return new Infantry();
            } else if ("Trooper".equals(type)) {
                return new Trooper();
            } else {
                System.out.println("请输入正确的类型!");
                return null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class Test {
        public static void main(String[] args) {
            Principal principal= new Principal();
            Soldier infantry= principal.produce("Infantry");
            Soldier trooper= principal.produce("Trooper");
            infantry.fight();
            trooper.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ?但是却产生了一个问题,张飞常常忘了Infantry和Trooper怎么拼写,怎么着都领不出兵。

    • 诸葛锦囊:我们可以用虎符啊!

    1.2 多个工厂方法模式

    于是练兵场负责人连日研发出了两种虎符,一种刻着Infantry,持有可调用步兵,一种刻着Trooper,持有可调用骑兵。
    这下张飞摆脱了拼写Infantry和Trooper的烦恼,效率大幅度提升。

    public class Principal{
    
        public Soldier produceInfantry() {
            return new Infantry();
        }
        public Soldier produceTrooper() {
            return new Trooper();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public class Test {
        public static void main(String[] args) {
            Principal principal= new Principal();
            Soldier infantry= principal.produceInfantry();
            Soldier trooper= principal.produceTrooper();
            infantry.fight();
            trooper.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ?但是时间久了,一个问题浮出水面,战事24小时都在发生,但是练兵场负责人却没有时时都在上班。

    • 诸葛锦囊:可以让持虎符者即可领兵!

    1.3 静态工厂方法模式

    练兵场出了新规,凡是持有练兵场出品虎符的人,即可享受负责人待遇进入领兵,无需通知负责人。

    public class Principal{
    
        public static Soldier produceInfantry() {
            return new Infantry();
        }
        public static Soldier produceTrooper() {
            return new Trooper();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public class Test {
        public static void main(String[] args) {
            Soldier infantry= Principal.produceInfantry();
            Soldier trooper= Principal.produceTrooper();
            infantry.fight();
            trooper.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • ?现在诸葛亮想为刘备练一些弓兵。但是有一个问题,一个练兵场只能练那么多种兵,而且为了更专业,最好一个练兵场只专门练一种兵。

    • 诸葛锦囊:为弓兵建一个弓兵练兵场!

    2 抽象工厂模式(Abstract Factory)

    于是在诸葛亮改良之后,刘备同意为步兵、骑兵和弓兵分别建一个练兵场,诸葛亮作为所有练兵场的管理员,负责派发所有的虎符。
    这时候想要领兵,按以下步骤,诸葛亮建对应的练兵场,将领到对应的练兵场,持有虎符,领兵。

    public interface Soldier{
        void fight();
    }
    
    • 1
    • 2
    • 3
    public class Infantry implements Soldier{
        @Override
        public void fight() {
            System.out.println("Infantry walk forward!");
        }
    }
    public class Archer implements Soldier{
    
        @Override
        public void fight() {
            System.out.println("Fire arrows!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class InfantryFactory{
    
        public Soldier produce() {
          	return new Infantry();
        }
    }
    public class ArcherFactory{
    
        public Soldier produce() {
          	return new Archer();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class Test {
        public static void main(String[] args) {
            Factory infantryFactory= new InfantryFactory();
            Infantry infantry = infantryFactory.produce();
            infantry.fight();
    
            Factory archerFactory= new ArcherFactory();
            Archer archer = archerFactory.produce();
            archer.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • ?现在,弓兵练起来了,诸葛亮开始考虑怎么得到箭。可以有两种途径,一个是自己造,一个是向曹操草船借箭。

    • 诸葛锦囊:有两个流水线,一个是造箭流水线,一个是借箭流水线!

    3 建造者模式(Builder)

    于是,总箭量有两个补充来源,一个是造箭工厂中造出来的箭,一个是草船上借出来的箭。
    比如要造n根箭,就向诸葛亮上书,诸葛亮就new出n个工厂箭加入箭库。要借m根箭,就向诸葛亮上书,诸葛亮就new出m个操草船箭加入箭库。

    public class ArrowBuilder {
    
        private List<Arrow> list = new ArrayList<Arrow>();
    
        public void produceByGrassboat(int count){
            for(int i=0; i<count; i++){
                list.add(new GrassboatArrow());
            }
        }
    
        public void produceByFactory(int count){
            for(int i=0; i<count; i++){
                list.add(new FactoryArrow());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public class Test {
        public static void main(String[] args) {
            ArrowBuilder arrowBuilder = new ArrowBuilder();
            // 草船借10根箭
            arrowBuilder.produceByGrassboat(10);
            // 工厂造5根箭
            arrowBuilder.produceByFactory(5);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4 单例模式(Singleton)

    诸葛亮作为丞相要发出独一无二的命令,所以军令状上面要有他的印章。但是怎么保证这个印章是只有他能造、且绝无仅有的呢?
    幸运的是,诸葛亮有一个非常聪明的发明家妻子。
    于是,只有他的妻子能造出这个印章,这保证了造印章的能力是私有的。
    且妻子有,就相当于诸葛亮有,所以相当于诸葛亮永远持有一个且只有一个私有的静态的印章instance。
    如果任何人要盖印,只能先找到诸葛亮,取得这独一无二的印章,然后调用盖印方法。

    public class Seal{
        /* 私有构造方法,防止被实例化 */
        private Seal() {
        }
    
        /* 此处使用一个内部类来维护单例 */
        private static class SealFactory {
            private static Seal instance = new Seal();
        }
    
        /* 获取实例 */
        public static Seal getInstance() {
            return SealFactory.instance;
        }
    
        /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
        public Object readResolve() {
            return getInstance();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5 原型模式(Prototype)

    孙悟空可以用身上的毫毛变出和自己一模一样的猴子,我们管复制品叫猴A。
    猴A毕竟还是孙悟空的毫毛,你敲一下猴A,孙悟空会有点刺痛。我们管这叫浅复制。
    但是当六耳猕猴变成了假孙悟空时,你就算把六耳猕猴打成肉酱,孙悟空也没事。我们管这叫深复制。

    public class SunWukong implements Cloneable {
     	
        private static final long serialVersionUID = 1L;
        private String string;
    
        private SerializableObject obj;
        
    	public Object clone() throws CloneNotSupportedException { 
    		SunWukong monkeyA = (SunWukong) super.clone(); 
    		return monkeyA; 
    	} 
    } 
    	public Object deepClone() throws IOException, ClassNotFoundException {
    
            /* 写入当前对象的二进制流 */
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
    
            /* 读出二进制流产生的新对象 */
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray(
            ));
            ObjectInputStream ois = new ObjectInputStream(bis);
            return ois.readObject();
        }
        
        public String getString() {
            return string;
        }
    
        public void setString(String string) {
            this.string = string;
        }
    
        public SerializableObject getObj() {
            return obj;
        }
    
        public void setObj(SerializableObject obj) {
            this.obj = obj;
        }
    }
    class SerializableObject implements Serializable {
        private static final long serialVersionUID = 1L;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    6 适配器模式(Adapter)

    6.1 类的适配器模式

    唐僧对如何管住孙悟空感到烦恼,于是观音菩萨给了他一个漂亮的金丝帽。
    这顶帽子有帽子的两个功能。一个是可以让别人看不出一个人头秃,从而增加颜值;另一个是尽量保证帽子能紧紧地套在佩戴者头上。
    但是,不仅如此,这顶金丝帽还套着一个金箍。只要念咒,这个金箍收紧,戴上的人就会服从管教。

    public class GoldHoop{
        public void tighten(){
            System.out.println("Tighten the Gold hoop......");
        }
    }
    public interface Hat{
        public void beingHandsome();
        public void tighten();
    }
    public class GoldHat extends GoldHoop implements Hat{
    
        @Override
        public void beingHandsome() {
            System.out.println("Handsome up......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • ? 但是,GoldHoop如果直接和GoldHat产生联系,孙悟空可能会发现这个陷阱。所以唐僧要找别的方式把GoldHoop藏在GoldHat里面。

    • 观音的建议:让GoldHoop不是GoldHat的祖先,而是直接成为GoldHat的组成成分。

    6.2 对象的适配器模式

    于是唐僧把GoldHoop缝进了GoldHat的内部,这下它看起来就是个普通帽子了。
    于是,孙悟空被唐僧诈骗,高兴地戴上了GoldHat。他因为GoldHat变帅了,却也因为帽子中的金箍,不得不跟随唐僧去西天取经。

    public class GoldHat implements Hat{
    	private GoldHoop goldHoop;
    
        public GoldHat (GoldHoop g){
            super();
            goldHoop=g;
        }
        @Override
        public void beingHandsome() {
            System.out.println("Handsome up......");
        }
        @Override
        public void tighten(){
            goldHoop.tighten();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6.3 接口的适配器模式

    西天取经时,藏经阁中有所有经书,但一旦进去就必须把里面的经书全带回去,包括一些无用的无字经书。
    如果唐僧一行人只想要其中的有字大乘经书带回东土大唐,只能向实现了藏经阁的如来佛讨要有字大乘经书。

    public interface ScriptureLibrary{
        public void bookHaveWord();
        public void bookDontHaveWord();
    }
    
    • 1
    • 2
    • 3
    • 4
    public abstract class Buddha implements ScriptureLibrary{
        public void bookHaveWord();
        public void bookDontHaveWord();
    }
    
    • 1
    • 2
    • 3
    • 4
    public class TangMonk extends Buddha {
        public void bookHaveWord(){
            System.out.println("Get book with word");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class Test {
        public static void main(String[] args) {
            Buddha tangMonk=new TangMonk();
            tangMonk.bookHaveWord();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7 装饰模式(Decorator)

    贾瑞瑞大爷一直觊觎王熙凤,以至于在一般波折后得了重病,这时跛足道人给了他一面叫做风月宝鉴的镜子,并且吩咐只可以看镜子的背面,不能看正面。
    贾瑞看了镜子的背面,却上面的呈现出来的骷髅吓了一跳,然后忍不住看了镜子的正面,发现骷髅变成王熙凤美貌的模样。
    色心上头的贾瑞没有意识到,镜子只是一个接口,不管是骷髅还是肉体都只是一种实现,但只有骷髅白骨才是所有人没有被修饰的模样。
    最终贾瑞被白骨修饰成的肉身而迷了心智,最终失去了生命。

    public interface Mirror{
        public void show();
    }
    
    • 1
    • 2
    • 3
    public class Bone implements Mirror{
        @Override
        public void show() {
            System.out.println("Scary human skeleton");
        }
    }
    public class BeautifulFace implements Mirror{
    
        private Mirror bone;
    
        public BeautifulFace(Mirror bone){
            super();
            this.bone=bone;
        }
    
        @Override
        public void show() {
            bone.show();
            System.out.println("Beautiful face");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public class Test {
        public static void main(String[] args) {
            Mirror back= new Bone();
            Mirror front = new BeautifulFace(back);
            front.show();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8 代理模式(Proxy)

    探春想将大观园的每一部分开发出对应的产业,但是一个人在这么多工作面前是分身乏术、且不够专业的。
    所以贾家婆子齐上阵,成为不同营生的管理者,让专业的人做专业的事,用不同的途径来实现创收这个目标。

    public interface Reformation {
        public void revenue();
    }
    
    • 1
    • 2
    • 3
    public class BambooForest implements Reformation  {
        @Override
        public void revenue() {
            System.out.println("Make money");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class Vanilla implements Reformation {
        @Override
        public void revenue() {
            System.out.println("Make money");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class BambooForestManager implements Reformation {
    
        private Reformation field;
    
        public BambooForestManager(){
            super();
            field=new BambooForest();
        }
    
        @Override
        public void revenue() {
            work();
            field.revenue();
        }
    
        public void before(){
            System.out.println("Cut the bamboo");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    public class VanillaManager implements Reformation {
    
        private Reformation field;
    
        public BambooForestManager(){
            super();
            field=new Vanilla();
        }
    
        @Override
        public void revenue() {
            work();
            field.revenue();
        }
    
        public void before(){
            System.out.println("Reap vanilla");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    9 外观模式(Facade)

    红楼梦人物之间的关系十分复杂,其间可能夹杂着爱情、友情、命运等情感。
    但是,如果考虑到他们之间的亲戚关系,可能会无法共情像木石前盟、金玉良缘之类的美好关系。
    所以我们把他们的亲戚关系放在一个Facade 类中,不直接在每个人的身上贴亲戚关系的标签(也即不让他们互相继承),降低人与人之间的耦合度。

    public class Baoyu{
    
        public void fatherConnect(){
            System.out.println("baoyu's father");
        }
        public void motherConnect(){
            System.out.println("baoyu's mother");
        }
    }
    public class Tanchun{
    
        public void fatherConnect(){
            System.out.println("tanchun's father");
        }
        public void motherConnect(){
            System.out.println("tanchun's mother");
        }
    }
    public class Baochai{
    
        public void fatherConnect(){
            System.out.println("baochai's father");
        }
        public void motherConnect(){
            System.out.println("baochai's mother");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    public class Facade{
        private Baoyu baoyu;
        private Tanchun tanchun;
        private Baochai baochai;
    
        public Computer(){
            baoyu= new Baoyu();
            tanchun= new Tanchun();
            baochai= new Baochai();
        }
    
        public void motherConnect(){
            baoyu.motherConnect()
            System.out.println("and");
            baochai.motherConnect()
            System.out.println("are sister.");
        }
    
        public void fatherConnect(){
            baoyu.fatherConnect()
            System.out.println("and");
            tanchun.fatherConnect()
            System.out.println("are the same one.");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    10 桥接模式(Bridge)

    宋江虽然没有什么战斗力,但是他的长处是把36天罡72地煞都团结在一起,所有的武将都遵从他的规定,并听从他的调用。
    当打仗的时候,吴用经过宋江的授权,可以自由派遣任意武将上场,然后这些武将发挥自己的长处。这样,宋江和吴用不需要知道怎么战斗,武将也只需要遵从规定、听从指挥。

    public interface MilitaryOfficer{
        public void fight();
    }
    
    • 1
    • 2
    • 3
    public class LinChong implements MilitaryOfficer{
    
        @Override
        public void fight() {
            System.out.println("LinChong fighting");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class ShiJing implements MilitaryOfficer{
    
        @Override
        public void fight() {
            System.out.println("ShiJing fighting");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public abstract class SongJiang{
        private MilitaryOfficer officer;
    
        public void setOfficer(MilitaryOfficer militaryOfficer){
            officer=militaryOfficer;
        }
    
        public MilitaryOfficer sendOfficer(){
            return officer;
        }
    
        public void fight(){
            officer.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    public class WuYong extends SongJiang{
        public void fight(){
            sendOfficer().fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class Test {
        public static void main(String[] args) {
            SongJiang commander = new WuYong();
    
            ShiJing shiJing = new ShiJing();
            commander.setOfficer(shiJing);
            commander.fight();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    11 组合模式(Composite)

    红楼梦有着复杂的人物亲戚关系,一般我们可以画一个族谱或者家谱来表示这个树状关系。

    public class TreeNode {
        private String name;
        private TreeNode parent;
        private Vector<TreeNode> children = new Vector<TreeNode>();
    
        public TreeNode(String name){
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public TreeNode getParent() {
            return parent;
        }
        public void setParent(TreeNode parent) {
            this.parent = parent;
        }
    
        //添加孩子节点
        public void add(TreeNode node){
            children.add(node);
        }
    
        //删除孩子节点
        public void remove(TreeNode node){
            children.remove(node);
        }
    
        //取得孩子节点
        public Enumeration<TreeNode> getChildren(){
            return children.elements();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    12 享元模式(Flyweight)

    孙悟空身上有100根超级毫毛,它们可以用来变成小猴。小猴有两个共有的属性:身高,体重。这些属性对于毫毛变的小猴来说都是一样的。但是在面对不同场景时,可能需要有持有不同武器的小猴,所以这个属性可以在实际造猴的时候设置。
    当孙悟空要造猴的时候,他从剩余的毫毛中拔出一根,然后变成小猴。给小猴不同的武器来造就不同的小猴。当小猴没有用了的时候,就要对其进行回收,这时孙悟空会把小猴变回毫毛,以维持自己的毫毛池。

    public class FurPool {
        private Vector<Fur> pool;
    
        /*公有属性*/
        private int height = 150;
        private int weight = 40;   
        Fur fur = null; 
    
        /*构造方法,做一些初始化工作*/
        private FurPool () {
            pool = new Vector<Fur>(poolSize);
    
            for (int i = 0; i < poolSize; i++) {
                try {
                    Class.forName("com.ChangeToMonkey");
                    fur = DriverManager.getFur(height , weight);
                    pool.add(fur);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /* 返回连接到连接池 */
        public synchronized void release() {
            pool.add(fur);
        }
    
        /* 返回连接池中的一根毫毛 */
        public synchronized Fur getFur() {
            if (pool.size() > 0) {
                Fur fur= pool.get(0);
                pool.remove(fur);
                return fur;
            } else {
                return null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    13 策略模式(strategy)

    贾宝玉要从宴会上溜出去,他有几个可选的策略:一个是谎称北静王请他去做客,一个谎称自己生病了,一个谎称自己要做功课。但是这些策略都需要一个策略的支持,那就是在门外备好逃跑用的马。
    所以贾宝玉会在每次需要溜走的时候,从策略接口中实现一个策略,然后执行逃脱计划escape(),其中的最后一步都是执行共有策略:备好逃跑用的马。

    public interface IStrategy {
        public int escape();
    }
    
    • 1
    • 2
    • 3
    public abstract class AbstractStrategy {
        public int[] runWithAHorse(){
        	System.out.println("Run with a horse");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class VisitBei extends AbstractStrategy implements IStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Visit Bei");
            runWithAHorse();
        }
    }
    public class Ill extends AbstractStrategy implements IStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Ill");
            runWithAHorse();
        }
    }
    public class DoHomework extends AbstractStrategy implements IStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Do Homework ");
            runWithAHorse();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    public class Test {
        public static void main(String[] args) {
            IStrategy doHomework = new DoHomework();
            doHomework.escape();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    14 模板方法模式(Template Method)

    贾政快要结束他的出差,回贾府检查贾宝玉的作业了。一点书法没练的贾宝玉快吓出病,于是众姐妹开始帮贾宝玉伪造书法作业。
    伪造书法作业不是一件简单的事情,需要贾宝玉自己先给出一个自己的笔迹模板,让姐妹们模仿。虽然都是写同样的笔迹,但是为了更好的搪塞过去,每个人帮忙写的内容都不一样。
    最后,贾宝玉用不同的内容、同样的笔迹,过了贾政的严父关。

    public abstract class AbstractStrategy {
        public int[] runWithAHorse(){
        	System.out.println("Run with a horse");
        }
        public final int escape(){
        	System.out.println("Run with a horse");
            return escape();
        }
        abstract public int escape();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public class VisitBei extends AbstractStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Visit Bei");
        }
    }
    public class Ill extends AbstractStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Ill");
        }
    }
    public class DoHomework extends AbstractStrategy implements IStrategy {
    
        @Override
        public int escape() {
            System.out.println("Pretend Do Homework ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public class Test {
        public static void main(String[] args) {
            AbstractStrategy doHomework = new DoHomework();
            doHomework.escape();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    15 观察者模式(Observer)

    每个注册为贾府管理者的人,都可以接收到贾家时刻的变化信息。这个信息由分管不同事务的高级婆子进行通知。
    在几十年里,贾母、王夫人、王熙凤先后注册为贾府管理者,加入贾府事务通知群。
    这几日,巡视的婆子发现府内一角有赌博行为,于是行动起来,调用notifyObservers权限,一次性通知了所有贾府管理者。

    public interface Administrator{
        public void update();
    }
    
    • 1
    • 2
    • 3
    public class JiaMu implements Administrator{
        @Override
        public void update() {
            System.out.println("JiaMu has received.");
        }
    }
    public class WangXifeng implements Administrator{
        @Override
        public void update() {
            System.out.println("WangXifeng has received.");
        }
    }
    public class Mrs.Wang implements Administrator{
        @Override
        public void update() {
            System.out.println("Mrs.Wang has received.");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public interface Stewards{
        /*增加观察者*/
        public void add(Administrator ad);
    
        /*删除观察者*/
        public void del(Administrator ad);
    
        /*通知所有的观察者*/
        public void notifyObservers();
    
        /*自身的操作*/
        public void operation();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public abstract class AbstractSteward implements Stewards{
        private Vector<Administrator> vector = new Vector<Administrator>();
        @Override
        public void add(Administrator ad) {
            vector.add(ad);
        }
    
        @Override
        public void del(Administrator ad) {
            vector.remove(ad);
        }
    
        @Override
        public void notifyObservers() {
            Enumeration<Administrator> enumo = vector.elements();
            while(enumo.hasMoreElements()){
                enumo.nextElement().update();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    public class Steward extends AbstractSteward{
        @Override
        public void operation() {
            System.out.println("update self!");
            notifyObservers();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class Test {
        public static void main(String[] args) {
            AbstractSteward steward= new Steward();
            steward.add(new WangXifeng());
            steward.add(new JiaMu());
            steward.operation();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    16 迭代子模式(Iterator)

    16.1 implements Iterator

    16.2 implements Collection

    17 责任链模式(Chain of Responsibility)

    大观园建成之后需要对里面的建筑起名,于是贾政又想通过这个方法来考察贾宝玉的文采。
    贾政带着贾宝玉逛了一圈园子,然后让贾宝玉为每个院子起名。
    但是贾宝玉起的名并不能作为最终结果,还是需要元春省亲的时候最终敲定。
    贾政->贾宝玉->元春,这就是责任链。

    public interface Handler {
        public void operator();
    }
    
    • 1
    • 2
    • 3
    public abstract class AbstractHandler {
    
        private Handler handler;
    
        public Handler getHandler() {
            return handler;
        }
    
        public void setHandler(Handler handler) {
            this.handler = handler;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class MyHandler extends AbstractHandler implements Handler {
    
        private String name;
    
        public MyHandler(String name) {
            this.name = name;
        }
    
        @Override
        public void operator() {
            System.out.println(name+" deal!");
            if(getHandler()!=null){
                getHandler().operator();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public class Test {
    
        public static void main(String[] args) {
            MyHandler h1 = new MyHandler("JiaZheng");
            MyHandler h2 = new MyHandler("JiaBaoyu");
            MyHandler h3 = new MyHandler("JiaYuanchun");
    
            h1.setHandler(h2);
            h2.setHandler(h3);
    
            h1.operator();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    18 命令模式(Command)

    在火烧联营时,诸葛亮下令让关羽去抓曹操。
    诸葛亮指定并发出抓曹操的命令,命令中指定了接收人是关羽,于是命令的执行即相当于关羽的进行了抓曹操行动。
    诸葛亮不会去关注到底关羽是怎么抓曹操的,只会要求关羽一定得去抓曹操。

    public interface Command {
        public void exe();
    }
    
    • 1
    • 2
    • 3
    public class MyCommand implements Command{
        private GuangYu receiver;
    
        public MyCommand(GuanYu receiver){
            this.receiver=receiver;
        }
    
        @Override
        public void exe() {
            receiver.action();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class GuanYu {
        public void action(){
            System.out.println("Command received.");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class ZhugeLiang{
        private Command command;
    
        public Commander(Command command){
            this.command=command;
        }
    
        public void action(){
            command.exe();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    19 备忘录模式(Memento)

    红楼梦中众女儿的前世今生都被记录在了薄命司的金陵一册中。
    金陵一册用判词和图画记录对众女儿命运,薄命司是存储金陵一册的地方。

    public class JinlingMemento {
    
        private String value;
    
        public JinlingMemento(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public class IllfatedDepartment{
    
        private JinlingMemento memento;
    
        public IllfatedDepartment(JinlingMemento memento) {
            this.memento = memento;
        }
    
        public JinlingMemento getMemento() {
            return memento;
        }
    
        public void setMemento(JinlingMemento memento) {
            this.memento = memento;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public class CourtVerdict{
        private String value;
    
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
        public Original(String value) {
            this.value = value;
        }
        public JinlingMemento createMemento(){
            return new JinlingMemento(value);
        }
    
        public void restoreMemento(JinlingMemento memento){
            this.value = memento.getValue();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    public class Test {
    
        public static void main(String[] args) {
    
            // 创建原始类
            CourtVerdict origin = new CourtVerdict("可叹停机德,堪怜咏絮才。");
    
            // 创建备忘录
            IllfatedDepartment storage = new IllfatedDepartment(origin.createMemento());
    
            // 修改原始类的状态
            System.out.println("初始化状态为:" + origin.getValue());
            origi.setValue("玉带林中挂,金钗雪里埋。");
            System.out.println("修改后的状态为:" + origin.getValue());
    
            // 回复原始类的状态
                    origin.restoreMemento(storage.getMemento());
            System.out.println("恢复后的状态为:" + origin.getValue());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    20 状态模式(State)

    在贾府的就餐流程中,有非常多种状态。
    要先噤声吃饭、再洗手、再用茶漱口、最后再喝茶,每个状态对应不同的操作。

    public class State {
    
        private String value;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public void methodEat(){
            System.out.println("Silence and Eat!");
        }
    
        public void methodWash(){
            System.out.println("Wash hand!");
        }
    
        public void methodGargle(){
            System.out.println("Gargle with tea!");
        }
    
        public void methodDrink(){
            System.out.println("Drink tea!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    public class Daiyu{
    
        private State state;
    
        public Context(State state) {
            this.state = state;
        }
    
        public State getState() {
            return state;
        }
    
        public void setState(State state) {
            this.state = state;
        }
    
        public void method() {
            if (state.getValue().equals("Eat")) {
                state.methodEat();
            } else if (state.getValue().equals("Wash"))
                state.methodWash();
            } else if (state.getValue().equals("Gargle"))
                state.methodGargle();
            } else if (state.getValue().equals("Drink"))
                state.methodDrink();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    public class Test {
        public static void main(String[] args) {
            State state = new State();
            Daiyu daiyu= new Daiyu(state);
    
            state.setValue("Eat");
            daiyu.methodEat();
            
            state.setValue("Wash");
            daiyu.methodWash();
            
            state.setValue("Gargle");
            daiyu.methodGargle();
    
            state.setValue("Drink");
            daiyu.methodEat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    21 访问者模式(Visitor)

    寿怡红群芳开夜宴:贾宝玉过生日没过瘾,在晚上还邀请众姐妹到怡红院玩抽花签。

    众姐妹想参与抽花签,需要经历以下流程:
    怡红院接受拜访;
    拜访人执行拜访功能;
    在拜访中执行怡红院的抽花签功能。

    public interface Visitor {
        public void visit(Subject sub);
    }
    
    • 1
    • 2
    • 3
    public class Daiyu implements Visitor {
    
        @Override
        public void visit(Building sub) {'
        	System.out.println("Daiyu "+sub.playDraw())
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public interface Building{
        public void accept(Visitor visitor);
        public String playDraw();
    }
    
    • 1
    • 2
    • 3
    • 4
    public class YiHongYuan implements Building{
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    
        @Override
        public String playDraw() {
            return "play draw lots";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class Test {
        public static void main(String[] args) {
            Visitor visitor = new Daiyu();
            Building sub = new YiHongYuan();
            sub.accept(visitor);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    22 中介者模式(Mediator)

    大观园的众屋舍是在贾宝玉和众姐妹搬入大观园的前就建好的。
    这时候的大观园是一个中介,当贾宝玉和众姐妹搬入时,他们通过选择自己在大观园中的位置来体现互相的亲疏远近,而无需尴尬的互相表明依赖关系,这样不利于人与人之间相处的和谐。

    public abstract class Role{
    
        private Mediator mediator;
    
        public Mediator getMediator(){
            return mediator;
        }
        public Role(Mediator mediator) {
            this.mediator = mediator;
        }
    
        public abstract void play();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class Daiyu extends Role{
    
        public Daiyu(Mediator mediator){
            super(mediator);
        }
    
        @Override
        public void play() {
            System.out.println("Daiyu play!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    public class Baoyu extends Role{
    
        public Baoyu(Mediator mediator){
            super(mediator);
        }
    
        @Override
        public void play() {
            System.out.println("Baoyu play!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    public interface Mediator {
        public void createMediator();
        public void playTogether();
    }
    
    • 1
    • 2
    • 3
    • 4
    public class GrandGarden implements Mediator {
    
        private Role daiyu;
        private Role baoyu;
    
        public Role getUser1() {
            return daiyu;
        }
    
        public Role getUser2() {
            return baoyu;
        }
    
        @Override
        public void createMediator() {
            daiyu= new Daiyu(this);
            baoyu= new Baoyu(this);
        }
    
        @Override
        public void playTogether() {
            daiyu.play();
            System.out.println("and");
            baoyu.play();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    public class Test { 
    	 public static void main(String[] args) { 
    		 Mediator mediator = new GrandGarden(); 
    		 mediator.createMediator(); 
    		 mediator.playTogether(); 
     	} 
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    23 解释器模式(Interpreter)

    etc.etc. 这个模式用的好少,懒得写故事了

  • 相关阅读:
    2022年整理最详细的java面试题、掌握这一套八股文、面试基础不成问题[吐血整理、纯手撸]
    OpenAI GPT-4 Turbo发布:开创AI新时代
    MybatisX插件 逆向工程
    深入理解Spring AOP中的@EnableAspectJAutoProxy
    VS Code结构体无法正确引出成员变量
    Effective C++改善程序与设计的55个具体做法 9. 杂项讨论
    Appium 结合 TestNG 并行执行测试
    把请求头信息添加到请求报文中,然后发送请求到淘宝,显示回复信息
    Go语言实践模式 - 函数选项模式(Functional Options Pattern)
    springAop原理分析-动态代理对象创建过程分析
  • 原文地址:https://blog.csdn.net/twi_twi/article/details/126566740