java设计模式_java设计模式下载 - CSDN
java设计模式 订阅
《Java设计模式》是2009年由清华大学出版社出版的图书,作者是耿祥义、张跃平。 展开全文
《Java设计模式》是2009年由清华大学出版社出版的图书,作者是耿祥义、张跃平。
信息
页    数
227页
作    者
耿祥义、张跃平
定    价
29.00元
装    帧
平装
书    名
Java设计模式
出版时间
2009年
开    本
16开
出版社
清华大学出版社
ISBN
9787302198048
Java设计模式内容简介
该书探讨在Java程序设计中怎样使用著名的23个设计模式。《Java设计模式》的目的是让读者不仅学习怎样在软件设计中使用好设计模式,更重要的是让读者通过学习使用设计模式深刻地理解面向对象的设计思想,以便更好地使用面向对象语言解决设计中的诸多问题。
收起全文
精华内容
参与话题
  • java设计模式(附实例和详解)

    千次阅读 多人点赞 2019-03-26 13:51:51
    总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 (2)结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合...

    一、概况

    总体来说设计模式分为三大类:

    (1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    (2)结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

    (3)行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    二、设计模式的六大原则

    1、开闭原则(Open Close Principle)

    开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。

    2、里氏代换原则(Liskov Substitution Principle)

    其官方描述比较抽象,可自行百度。实际上可以这样理解:(1)子类的能力必须大于等于父类,即父类可以使用的方法,子类都可以使用。(2)返回值也是同样的道理。假设一个父类方法返回一个List,子类返回一个ArrayList,这当然可以。如果父类方法返回一个ArrayList,子类返回一个List,就说不通了。这里子类返回值的能力是比父类小的。(3)还有抛出异常的情况。任何子类方法可以声明抛出父类方法声明异常的子类。 
    而不能声明抛出父类没有声明的异常。

    3、依赖倒转原则(Dependence Inversion Principle)

    这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。

    4、接口隔离原则(Interface Segregation Principle)

    这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

    5、迪米特法则(最少知道原则)(Demeter Principle)

    为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

    6、合成复用原则(Composite Reuse Principle)

    原则是尽量使用合成/聚合的方式,而不是使用继承。

    三、创建型模式

    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    3.1、工厂方法模式

    工厂方法模式分为三种:普通工厂模式、多个工厂方法模式和静态工厂方法模式。

    3.1.1、普通工厂模式

    普通工厂模式就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

    package com.mode.create;
    
    public interface MyInterface {
        public void print();
    }
    package com.mode.create;
    
    public class MyClassOne implements MyInterface {
    
        @Override
        public void print() {
            System.out.println("MyClassOne");
        }
    
    }
    • kage com.mode.create; public class MyClassTwo implements MyInterface { @Override public void print() { System.out.println("MyClassTwo"); } }
    •  

    package com.mode.create;

    public class MyFactory {

    public MyInterface produce(String type) {  
        if ("One".equals(type)) {  
            return new MyClassOne();  
        } else if ("Two".equals(type)) {  
            return new MyClassTwo();  
        } else {  
            System.out.println("没有要找的类型");  
            return null;  
        }  
    }
    
    •  




    package com.mode.create;

    public class FactoryTest {

    public static void main(String[] args){
        MyFactory factory = new MyFactory();  
        MyInterface myi = factory.produce("One");  
        myi.print();
    }
    


    “` 
    FactoryTest的运行结果我想应该很明显了。

    再回头来理解这句话:普通工厂模式就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

    3.1.2、多个工厂方法模式

    多个工厂方法模式,是对普通工厂方法模式的改进,多个工厂方法模式就是提供多个工厂方法,分别创建对象。

    直接看代码吧,我们修改MyFactory和FactoryTest如下:

    package com.mode.create;
    
    public class MyFactory {
    
        public MyInterface produceOne() {
            return new MyClassOne();
        }
    
        public MyInterface produceTwo() {
            return new MyClassTwo();
        }
    
    }

     

    package com.mode.create;
    
    public class FactoryTest {
    
        public static void main(String[] args){
            MyFactory factory = new MyFactory();  
            MyInterface myi = factory.produceOne();
            myi.print();
        }
    
    }

    运行结果也是十分明显了。

    再回头来理解这句话:多个工厂方法模式,是对普通工厂方法模式的改进,多个工厂方法模式就是提供多个工厂方法,分别创建对象。

    3.1.3、静态工厂方法模式

    静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    直接看代码吧,我们修改MyFactory和FactoryTest如下:

    package com.mode.create;
    
    public class MyFactory {
    
        public static MyInterface produceOne() {
            return new MyClassOne();
        }
    
        public static MyInterface produceTwo() {
            return new MyClassTwo();
        }
    
    }
    package com.mode.create;
    
    public class FactoryTest {
    
        public static void main(String[] args){ 
            MyInterface myi = MyFactory.produceOne();
            myi.print();
        }
    
    }

    运行结果依旧很明显。

    再回顾:静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    3.2、抽象工厂模式

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则。

    为解决这个问题,我们来看看抽象工厂模式:创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

    这样就符合闭包原则了。

    下面来看看代码:

    MyInterface、MyClassOne、MyClassTwo不变。

    新增如下接口和类:

    package com.mode.create;
    
    public interface Provider {
        public MyInterface produce(); 
    }
    package com.mode.create;
    
    public class MyFactoryOne implements Provider {
    
        @Override
        public MyInterface produce() {
            return new MyClassOne();
        }
    
    }
    package com.mode.create;
    
    public class MyFactoryTwo implements Provider {
    
        @Override
        public MyInterface produce() {
            return new MyClassTwo();
        }
    
    }

    修改测试类FactoryTest如下:

    package com.mode.create;
    
    public class FactoryTest {
    
        public static void main(String[] args){ 
            Provider provider = new MyFactoryOne();
            MyInterface myi = provider.produce();
            myi.print();
        }
    
    }

    运行结果依旧显然。

    再回顾:抽象工厂模式就是创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

    3.3、单例模式

    单例模式,不需要过多的解释。

    直接看代码吧:

    package test;
    
    public class MyObject {
    
        private static MyObject myObject;
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            if (myObject != null) {
            } else {
                myObject = new MyObject();
            }
            return myObject;
        }
    
    }

    但是这样会引发多线程问题,详细解说可以看《Java多线程编程核心技术》书中的第六章。博主之前推荐过这本书,里面有电子完整版下载地址:http://blog.csdn.net/u013142781/article/details/50805655

    3.4、建造者模式

    建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    字面看来非常抽象,实际上它也十分抽象!!!!

    建造者模式通常包括下面几个角色:

    (1) Builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。

    (2) ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。

    (3)Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。

    (4)Product:要创建的复杂对象。

    在游戏开发中建造小人是经常的事了,要求是:小人必须包括头,身体和脚。

    下面我们看看如下代码:

    Product(要创建的复杂对象。):

    package com.mode.create;
    
    public class Person {
    
        private String head;
        private String body;
        private String foot;
    
        public String getHead() {
            return head;
        }
    
        public void setHead(String head) {
            this.head = head;
        }
    
        public String getBody() {
            return body;
        }
    
        public void setBody(String body) {
            this.body = body;
        }
    
        public String getFoot() {
            return foot;
        }
    
        public void setFoot(String foot) {
            this.foot = foot;
        }
    }

    Builder(给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。):

    package com.mode.create;
    
    public interface PersonBuilder {
        void buildHead();
        void buildBody();
        void buildFoot();
        Person buildPerson();
    }

    ConcreteBuilder(实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。):

    package com.mode.create;
    
    public class ManBuilder implements PersonBuilder {
    
        Person person;
    
        public ManBuilder() {
            person = new Person();
        }
    
        public void buildBody() {
            person.setBody("建造男人的身体");
        }
    
        public void buildFoot() {
            person.setFoot("建造男人的脚");
        }
    
        public void buildHead() {
            person.setHead("建造男人的头");
        }
    
        public Person buildPerson() {
            return person;
        }
    
    }

    Director(调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。):

    package com.mode.create;
    
    public class PersonDirector {
        public Person constructPerson(PersonBuilder pb) {
            pb.buildHead();
            pb.buildBody();
            pb.buildFoot();
            return pb.buildPerson();
        }
    }

    测试类:

    package com.mode.create;
    
    public class Test {
        public static void main(String[] args) {
            PersonDirector pd = new PersonDirector();
            Person person = pd.constructPerson(new ManBuilder());
            System.out.println(person.getBody());
            System.out.println(person.getFoot());
            System.out.println(person.getHead());
        }
    }

    运行结果: 
     
    回顾:建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    3.5、原型模式

    该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。

    说道复制对象,我将结合对象的浅复制和深复制来说一下,首先需要了解对象深、浅复制的概念:

    浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

    深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。

    写一个深浅复制的例子:

    package com.mode.create;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class Prototype implements Cloneable, Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private int base;
    
        private Integer obj;
    
         /* 浅复制 */  
        public Object clone() throws CloneNotSupportedException {
            // 因为Cloneable接口是个空接口,你可以任意定义实现类的方法名
            // 如cloneA或者cloneB,因为此处的重点是super.clone()这句话
            // super.clone()调用的是Object的clone()方法
            // 而在Object类中,clone()是native(本地方法)的
            Prototype proto = (Prototype) super.clone();
            return proto;
        }
    
        /* 深复制 */
        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 int getBase() {
            return base;
        }
    
        public void setBase(int base) {
            this.base = base;
        }
    
        public Integer getObj() {
            return obj;
        }
    
        public void setObj(Integer obj) {
            this.obj = obj;
        }
    
    }

    测试类:

    package com.mode.create;
    
    import java.io.IOException;
    
    public class Test {
        public static void main(String[] args) throws CloneNotSupportedException,
                ClassNotFoundException, IOException {
            Prototype prototype = new Prototype();
            prototype.setBase(1);
            prototype.setObj(new Integer(2));
            /* 浅复制 */ 
            Prototype prototype1 = (Prototype) prototype.clone();
            /* 深复制 */
            Prototype prototype2 = (Prototype) prototype.deepClone();
            System.out.println(prototype1.getObj()==prototype1.getObj());
            System.out.println(prototype1.getObj()==prototype2.getObj());
        }
    }

     

    展开全文
  • Java23种设计模式——最牛逼的例子(精)

    万次阅读 多人点赞 2018-08-08 10:57:38
    一、创建型模式 1、FACTORY:追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,固然口味有所不同,但不管你带MM往麦当劳或肯德基,只管向服务员说;来四个鸡翅就行了。麦当劳和肯德基就是生产鸡翅...

    一、创建型模式
      1、FACTORY:追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,固然口味有所不同,但不管你带MM往麦当劳或肯德基,只管向服务员说;来四个鸡翅就行了。麦当劳和肯德基就是生产鸡翅的Factory
      工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。

       2、BUILDER:MM最爱听的就是;我爱你;这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种 语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出;我爱你;这句话了,国外的MM也可以轻松搞掂,这就是我的;我爱 你;builder。(这一定比美军在伊拉克用的翻译机好卖)
      建造模式:将产品的内部表象和产品的天生过程分割开来,从而使一个建造过程天生具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。

      3、FACTORY METHOD:请MM往麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说;要一个汉堡;,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
      工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类往做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

      4、PROTOTYPE:跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)
       原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式答应动态的增加或 减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。

      5、SINGLETON:俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道;老公;,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
      单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的;单一实例;的需求时才可使用。

    二、结构型模式
      6、ADAPTER:在朋友聚会上碰到了一个美女Sarah,从香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)
      适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。

      7、BRIDGE:早上碰到MM,要说早上好,晚上碰到MM,要说晚上好;碰到MM穿了件新衣服,要说你的衣服好漂亮哦,碰到MM新做的发型,要说你的头发好漂亮哦。不要问我;早上碰到MM新做了个发型怎么说;这种题目,自己用BRIDGE组合一下不就行了
      桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继续关系,从而使两者可以独立的变化。

       8、COMPOSITE:Mary今天过生日。;我过生日,你要送我一件礼物。;;嗯,好吧,往商店,你自己挑。;;这件T恤挺漂亮,买,这条裙子好 看,买,这个包也不错,买。;;喂,买了三件了呀,我只答应送一件礼物的哦。;;什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起 来。;;;,MM都会用Composite模式了,你会了没有?
      合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。

       9、DECORATOR:Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我往年在西岳顶上照的照片,在背面 写上;最好的的礼物,就是爱你的Fita;,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装 起来,我们都是Decorator,终极都在修饰我这个人呀,怎么样,看懂了吗?
      装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继续关系的一个替换方案,提供比继续更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。

       10、FACADE:我有一个专业的Nikon相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好 相机有Facade设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样MM也可以用这个相机给我拍张照片了。
      门面模式:外部与一个子系统的通讯必须通过一个同一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。

       11、FLYWEIGHT:天天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上 MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。
       享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外 蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共 享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出往。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建 被共享的对象。享元模式大幅度的降低内存中对象的数目。

      12、PROXY:跟MM在网上聊天,一开头总是;hi,你好;,;你从哪儿来呀?;;你多大了?;;身高多少呀?;这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自动的回答,接收到其他的话时再通知我回答,怎么样,酷吧。
       代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些 情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可 以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传进。

    三、行为模式
       13、CHAIN OF RESPONSIBLEITY:晚上往上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上;Hi,可以做我的女朋友 吗?假如不愿意请向前传;,纸条就一个接一个的传上往了,糟糕,传到第一排的MM把纸条传给老师了,听说是个老童贞呀,快跑!
      责任链模式:在 责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪 一个对象终极处理这个请求,系统可以在不影响客户真个情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以终 极不被任何接收端对象所接受。

      14、COMMAND:俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信 息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:;我同时 给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。;,:-(
      命令模式:命令模式把一个请求或者操纵封装到一个对象中。命令模 式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式答应请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接 口,更不必知道请求是怎么被接收,以及操纵是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。

      15、INTERPRETER:俺有一个《泡MM真经》,上面有各种泡MM的攻略,比如说往吃西餐的步骤、往看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了。
       解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器 模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需 要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的 任何排列组合都是一个语言。

      16、ITERATOR:我爱上了Mary,不顾一切的向她求婚。
      Mary:;想要我跟你结婚,得答应我的条件;
      我:;什么条件我都答应,你说吧;
      Mary:;我看上了那个一克拉的钻石;
      我:;我买,我买,还有吗?;
      Mary:;我看上了湖边的那栋别墅;
      我:;我买,我买,还有吗?;
      Mary:;你的小弟弟必须要有50cm长;
      我脑袋嗡的一声,坐在椅子上,一咬牙:;我剪,我剪,还有吗?;
       迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的 容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭 代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。

      17、MEDIATOR:四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话。
       调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以疏松偶合。当某些对象之间的作用发生改变时,不 会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和 协作抽象化,把对象在小标准的行为上与其他对象的相互作用分开处理。

      18、MEMENTO:同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不兴奋的哦,幸亏我有个备忘录,刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。
      备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。

      19、OBSERVER:想知道咱们公司最新MM情报吗?加进公司的MM情报邮件组就行了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦
      观察者模式:观察者模式定义了一种一队多的依靠关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

       20、STATE:跟MM交往时,一定要留意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上往看电影,对你没爱好的MM就会说;有事 情啦;,对你不讨厌但还没喜欢上的MM就会说;好啊,不过可以带上我同事么?;,已经喜欢上你的MM就会说;几点钟?看完电影再往泡吧怎么样?;,当然你 看电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。
      状态模式:状态模式答应一个对象在其内部状态改变的时候改变行为。 这个对象看上往象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的 意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便 改变所选的子类。

      21、STRATEGY:跟不同类型的MM约会,要用不同的策略,有的请电影比较好,有的则往吃小吃效果不错,有的往海边浪漫最合适,单目的都是为了得到MM的芳心,我的追MM锦囊中有好多Strategy哦。
       策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户真个情 况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会 影响到环境和客户端。

      22、TEMPLATE METHOD::看过《如何说服女生上床》这部经典文章吗?女生从熟悉到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进往八 大步骤(Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦(具体实现);
      模板方法模 式:模板方法模式预备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同 的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类往实现。

      23、 VISITOR:情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪 搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多 了;
      访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操纵。一旦这些操纵需要修改的话,接受这个操纵的数据结构可以保持 不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操纵之间的耦合解脱开,使得操纵集合可以相对自由的演化。访问者模式使得增 加新的操纵变的很轻易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时, 要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。

    展开全文
  • Java 中几种常用设计模式

    万次阅读 多人点赞 2018-08-09 16:51:53
    Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、...

    Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。
    总体来说设计模式分为三大类:
    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    1. 单例模式

    所谓的单例设计指的是一个类只允许产生一个实例化对象。
    最好理解的一种设计模式,分为懒汉式和饿汉式。

    饿汉式:构造方法私有化,外部无法产生新的实例化对象,只能通过static方法取得实例化对象

    class Singleton {
        /**
         * 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
         */
        private static Singleton instance = new Singleton();
        /**
         * private 声明构造
         */
        private Singleton() {
    
        }
        /**
         * 返回对象实例
         */
        public static Singleton getInstance() {
            return instance;
        }
    
        public void print() {
            System.out.println("Hello Singleton...");
        }
    }

    懒汉式:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作

    class Singleton {
    
        /**
         * 声明变量
         */
        private static volatile Singleton singleton = null;
    
        /**
         * 私有构造方法
         */
        private Singleton() {
    
        }
    
        /**
         * 提供对外方法
         * @return 
         */
        public static Singleton getInstance() {
            // 还未实例化
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
        public void print() {
            System.out.println("Hello World");
        }
    }

    当多个线程并发执行 getInstance 方法时,懒汉式会存在线程安全问题,所以用到了 synchronized 来实现线程的同步,当一个线程获得锁的时候其他线程就只能在外等待其执行完毕。而饿汉式则不存在线程安全的问题。

    2. 工厂设计模式

    工厂模式分为工厂方法模式和抽象工厂模式。

    工厂方法模式

    工厂方法模式:
    1. 工厂方法模式分为三种:普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
    2. 多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
    3. 静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    1. 普通工厂模式

    建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

    interface Sender {
        void Send();
    }
    
    class MailSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is mail sender...");
        }
    }
    
    class SmsSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is sms sender...");
        }
    }
    
    public class FactoryPattern {
        public static void main(String[] args) {
            Sender sender = produce("mail");
            sender.Send();
        }
        public static Sender produce(String str) {
            if ("mail".equals(str)) {
                return new MailSender();
            } else if ("sms".equals(str)) {
                return new SmsSender();
            } else {
                System.out.println("输入错误...");
                return null;
            }
        }
    }

    2. 多个工厂方法模式

    该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

    interface Sender {
        void Send();
    }
    
    class MailSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is mail sender...");
        }
    }
    
    class SmsSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is sms sender...");
        }
    }
    
    class SendFactory {
        public Sender produceMail() {
            return new MailSender();
        }
    
        public Sender produceSms() {
            return new SmsSender();
        }
    }
    
    public class FactoryPattern {
        public static void main(String[] args) {
            SendFactory factory = new SendFactory();
            Sender sender = factory.produceMail();
            sender.Send();
        }
    }

    3. 静态工厂方法模式

    将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    interface Sender {
        void Send();
    }
    
    class MailSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is mail sender...");
        }
    }
    
    class SmsSender implements Sender {
    
        @Override
        public void Send() {
            System.out.println("This is sms sender...");
        }
    }
    
    class SendFactory {
        public static Sender produceMail() {
            return new MailSender();
        }
    
        public static Sender produceSms() {
            return new SmsSender();
        }
    }
    
    public class FactoryPattern {
        public static void main(String[] args) {
            Sender sender = SendFactory.produceMail();
            sender.Send();
        }
    }

    抽象工厂模式

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要扩展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?
    那么这就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

    interface Provider {
        Sender produce();
    }
    
    interface Sender {
        void Send();
    }
    
    class MailSender implements Sender {
    
        public void Send() {
            System.out.println("This is mail sender...");
        }
    }
    
    class SmsSender implements Sender {
    
        public void Send() {
            System.out.println("This is sms sender...");
        }
    }
    
    class SendMailFactory implements Provider {
    
        public Sender produce() {
            return new MailSender();
        }
    }
    
    class SendSmsFactory implements Provider {
    
        public Sender produce() {
            return new SmsSender();
        }
    }
    
    
    public class FactoryPattern {
        public static void main(String[] args) {
            Provider provider = new SendMailFactory();
            Sender sender = provider.produce();
            sender.Send();
        }
    }

    3. 建造者模式

    工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author: LiuWang
     * @Created: 2018/8/6 17:47
     */
    
    abstract class Builder {
        /**
         * 第一步:装CPU
         */
       public abstract void buildCPU();
    
        /**
         * 第二步:装主板
         */
        public abstract void buildMainBoard();
    
        /**
         * 第三步:装硬盘
         */
        public abstract void buildHD();
    
        /**
         * 获得组装好的电脑
         * @return
         */
        public abstract Computer getComputer();
    }
    
    /**
     * 装机人员装机
     */
    class Director {
        public void Construct(Builder builder) {
            builder.buildCPU();
            builder.buildMainBoard();
            builder.buildHD();
        }
    }
    
    /**
     * 具体的装机人员
     */
    class ConcreteBuilder extends  Builder {
    
        Computer computer = new Computer();
    
        @Override
        public void buildCPU() {
            computer.Add("装CPU");
        }
    
        @Override
        public void buildMainBoard() {
            computer.Add("装主板");
        }
    
        @Override
        public void buildHD() {
            computer.Add("装硬盘");
        }
    
        @Override
        public Computer getComputer() {
            return computer;
        }
    }
    
    class Computer {
    
        /**
         * 电脑组件集合
         */
        private List<String> parts = new ArrayList<String>();
    
        public void Add(String part) {
            parts.add(part);
        }
    
        public void print() {
            for (int i = 0; i < parts.size(); i++) {
                System.out.println("组件:" + parts.get(i) + "装好了...");
            }
            System.out.println("电脑组装完毕...");
        }
    }
    
    public class BuilderPattern {
    
        public static void main(String[] args) {
            Director director = new Director();
            Builder builder = new ConcreteBuilder();
            director.Construct(builder);
            Computer computer = builder.getComputer();
            computer.print();
        }
    }

    4. 适配器设计模式

    适配器模式是将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的的类的兼容性问题。主要分三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

    1. 类的适配器模式:

    class Source {
        public void method1() {
            System.out.println("This is original method...");
        }
    }
    
    interface Targetable {
    
        /**
         * 与原类中的方法相同
         */
        public void method1();
    
        /**
         * 新类的方法
         */
        public void method2();
    }
    
    class Adapter extends Source implements Targetable {
    
        @Override
        public void method2() {
            System.out.println("This is the targetable method...");
        }
    }
    
    public class AdapterPattern {
        public static void main(String[] args) {
            Targetable targetable = new Adapter();
            targetable.method1();
            targetable.method2();
        }
    }

    2. 对象的适配器模式

    基本思路和类的适配器模式相同,只是将Adapter 类作修改,这次不继承Source 类,而是持有Source 类的实例,以达到解决兼容性的问题。

    class Source {
        public void method1() {
            System.out.println("This is original method...");
        }
    }
    
    interface Targetable {
    
        /**
         * 与原类中的方法相同
         */
        public void method1();
    
        /**
         * 新类的方法
         */
        public void method2();
    }
    
    class Wrapper implements Targetable {
    
        private Source source;
    
        public Wrapper(Source source) {
            super();
            this.source = source;
        }
    
        @Override
        public void method1() {
            source.method1();
        }
    
        @Override
        public void method2() {
            System.out.println("This is the targetable method...");
        }
    }
    
    public class AdapterPattern {
        public static void main(String[] args) {
            Source source = new Source();
            Targetable targetable = new Wrapper(source);
            targetable.method1();
            targetable.method2();
        }
    }

    3. 接口的适配器模式

    接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

    /**
     * 定义端口接口,提供通信服务
     */
    interface Port {
        /**
         * 远程SSH端口为22
         */
        void SSH();
    
        /**
         * 网络端口为80
         */
        void NET();
    
        /**
         * Tomcat容器端口为8080
         */
        void Tomcat();
    
        /**
         * MySQL数据库端口为3306
         */
        void MySQL();
    }
    
    /**
     * 定义抽象类实现端口接口,但是什么事情都不做
     */
    abstract class Wrapper implements Port {
        @Override
        public void SSH() {
    
        }
    
        @Override
        public void NET() {
    
        }
    
        @Override
        public void Tomcat() {
    
        }
    
        @Override
        public void MySQL() {
    
        }
    }
    
    /**
     * 提供聊天服务
     * 需要网络功能
     */
    class Chat extends Wrapper {
        @Override
        public void NET() {
            System.out.println("Hello World...");
        }
    }
    
    /**
     * 网站服务器
     * 需要Tomcat容器,Mysql数据库,网络服务,远程服务
     */
    class Server extends Wrapper {
        @Override
        public void SSH() {
            System.out.println("Connect success...");
        }
    
        @Override
        public void NET() {
            System.out.println("WWW...");
        }
    
        @Override
        public void Tomcat() {
            System.out.println("Tomcat is running...");
        }
    
        @Override
        public void MySQL() {
            System.out.println("MySQL is running...");
        }
    }
    
    public class AdapterPattern {
    
        private static Port chatPort = new Chat();
        private static Port serverPort = new Server();
    
        public static void main(String[] args) {
            // 聊天服务
            chatPort.NET();
    
            // 服务器
            serverPort.SSH();
            serverPort.NET();
            serverPort.Tomcat();
            serverPort.MySQL();
        }
    }

    5. 装饰模式

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

    interface Shape {
        void draw();
    }
    
    /**
     * 实现接口的实体类
     */
    class Rectangle implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Shape: Rectangle...");
        }
    }
    
    class Circle implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Shape: Circle...");
        }
    }
    
    /**
     * 创建实现了 Shape 接口的抽象装饰类。
     */
    abstract class ShapeDecorator implements Shape {
        protected Shape decoratedShape;
    
        public ShapeDecorator(Shape decoratedShape) {
            this.decoratedShape = decoratedShape;
        }
    
        @Override
        public void draw() {
            decoratedShape.draw();
        }
    }
    
    /**
     *  创建扩展自 ShapeDecorator 类的实体装饰类。
     */
    class RedShapeDecorator extends ShapeDecorator {
    
        public RedShapeDecorator(Shape decoratedShape) {
            super(decoratedShape);
        }
    
        @Override
        public void draw() {
            decoratedShape.draw();
            setRedBorder(decoratedShape);
        }
    
        private void setRedBorder(Shape decoratedShape) {
            System.out.println("Border Color: Red");
        }
    }
    
    /**
     * 使用 RedShapeDecorator 来装饰 Shape 对象。
     */
    public class DecoratorPattern {
        public static void main(String[] args) {
            Shape circle = new Circle();
            Shape redCircle = new RedShapeDecorator(new Circle());
            Shape redRectangle = new RedShapeDecorator(new Rectangle());
            System.out.println("Circle with normal border");
            circle.draw();
    
            System.out.println("\nCircle of red border");
            redCircle.draw();
    
            System.out.println("\nRectangle of red border");
            redRectangle.draw();
        }
    }

    6. 策略模式

    策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

    /**
     * 抽象算法的策略类,定义所有支持的算法的公共接口
     */
    abstract class Strategy {
        /**
         * 算法方法
         */
        public abstract void AlgorithmInterface();
    }
    
    /**
     * 具体算法A
     */
    class ConcreteStrategyA extends Strategy {
        //算法A实现方法
        @Override
        public void AlgorithmInterface() {
            System.out.println("算法A的实现");
        }
    }
    
    /**
     * 具体算法B
     */
    class ConcreteStrategyB extends Strategy {
        /**
         * 算法B实现方法
         */
        @Override
        public void AlgorithmInterface() {
            System.out.println("算法B的实现");
        }
    }
    
    /**
     * 具体算法C
     */
    class ConcreteStrategyC extends Strategy {
        @Override
        public void AlgorithmInterface() {
            System.out.println("算法C的实现");
        }
    }
    
    /**
     * 上下文,维护一个对策略类对象的引用
     */
    class Context {
        Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public void contextInterface(){
            strategy.AlgorithmInterface();
        }
    }
    
    /**
     * 客户端代码:实现不同的策略
     */
    public class StrategyPattern {
        public static void main(String[] args) {
    
            Context context;
    
            context = new Context(new ConcreteStrategyA());
            context.contextInterface();
    
            context = new Context(new ConcreteStrategyB());
            context.contextInterface();
    
            context = new Context(new ConcreteStrategyC());
            context.contextInterface();
        }
    }

    7. 代理模式

    代理模式指给一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理可以分为静态代理和动态代理。
    通过代理模式,可以利用代理对象为被代理对象添加额外的功能,以此来拓展被代理对象的功能。可以用于计算某个方法执行时间,在某个方法执行前后记录日志等操作。

    1. 静态代理

    静态代理需要我们写出代理类和被代理类,而且一个代理类和一个被代理类一一对应。代理类和被代理类需要实现同一个接口,通过聚合使得代理对象中有被代理对象的引用,以此实现代理对象控制被代理对象的目的。

    /**
     * 代理类和被代理类共同实现的接口
     */
    interface IService {
    
        void service();
    }
    
    
    /**
     * 被代理类
     */
    class Service implements IService{
    
        @Override
        public void service() {
            System.out.println("被代理对象执行相关操作");
        }
    }
    
    /**
     * 代理类
     */
    class ProxyService implements IService{
        /**
         * 持有被代理对象的引用
         */
        private IService service;
    
        /**
         * 默认代理Service类
         */
        public ProxyService() {
            this.service = new Service();
        }
    
        /**
         * 也可以代理实现相同接口的其他类
         * @param service
         */
        public ProxyService(IService service) {
            this.service = service;
        }
    
        @Override
        public void service() {
            System.out.println("开始执行service()方法");
            service.service();
            System.out.println("service()方法执行完毕");
        }
    }
    
    
    //测试类
    public class ProxyPattern {
    
        public static void main(String[] args) {
            IService service = new Service();
            //传入被代理类的对象
            ProxyService proxyService = new ProxyService(service);
            proxyService.service();
        }
    }

    2. 动态代理

    JDK 1.3 之后,Java通过java.lang.reflect包中的三个类Proxy、InvocationHandler、Method来支持动态代理。动态代理常用于有若干个被代理的对象,且为每个被代理对象添加的功能是相同的(例如在每个方法运行前后记录日志)。

    动态代理的代理类不需要我们编写,由Java自动产生代理类源代码并进行编译最后生成代理对象。
    创建动态代理对象的步骤:
    1. 指明一系列的接口来创建一个代理对象
    2. 创建一个调用处理器(InvocationHandler)对象
    3. 将这个代理指定为某个其他对象的代理对象
    4. 在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要的操作

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 代理类和被代理类共同实现的接口
     */
    interface IService {
        void service();
    }
    
    class Service implements IService{
    
        @Override
        public void service() {
            System.out.println("被代理对象执行相关操作");
        }
    }
    
    class ServiceInvocationHandler implements InvocationHandler {
    
        /**
         * 被代理的对象
         */
        private Object srcObject;
    
        public ServiceInvocationHandler(Object srcObject) {
            this.srcObject = srcObject;
        }
    
        @Override
        public Object invoke(Object proxyObj, Method method, Object[] args) throws Throwable {
            System.out.println("开始执行"+method.getName()+"方法");
            //执行原对象的相关操作,容易忘记
            Object returnObj = method.invoke(srcObject,args);
            System.out.println(method.getName()+"方法执行完毕");
            return returnObj;
        }
    }
    
    public class ProxyPattern {
        public static void main(String[] args) {
            IService service = new Service();
            Class<? extends IService> clazz = service.getClass();
    
            IService proxyService = (IService) Proxy.newProxyInstance(clazz.getClassLoader(),
                                            clazz.getInterfaces(), new ServiceInvocationHandler(service));
            proxyService.service();
        }
    }
    展开全文
  • Java开发中的23种设计模式详解

    万次阅读 多人点赞 2019-01-25 11:28:26
    Java开发中的23种设计模式详解
                   

    转自:http://zz563143188.iteye.com/blog/1847029


     

     

    设计模式(Design Patterns)

                                      ——可复用面向对象软件的基础

    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。本章系Java之美[从菜鸟到高手演变]系列之设计模式,我们会以理论与实践相结合的方式来进行本章的学习,希望广大程序爱好者,学好设计模式,做一个优秀的软件工程师!

    在阅读过程中有任何问题,请及时联系:egg。

    邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef

    如有转载,请说明出处:http://blog.csdn.net/zhangerqing

    企业级项目实战(带源码)地址http://zz563143188.iteye.com/blog/1825168

    23种模式java实现源码收集五年的开发资料下载地址:  http://pan.baidu.com/share/link?shareid=3739316113&uk=4076915866#dir/path=%2Fstudy

    一、设计模式的分类

    总体来说设计模式分为三大类:

    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:

     

    二、设计模式的六大原则

    1、开闭原则(Open Close Principle)

    开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

    2、里氏代换原则(Liskov Substitution Principle)

    里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

    3、依赖倒转原则(Dependence Inversion Principle)

    这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。

    4、接口隔离原则(Interface Segregation Principle)

    这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

    5、迪米特法则(最少知道原则)(Demeter Principle)

    为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

    6、合成复用原则(Composite Reuse Principle)

    原则是尽量使用合成/聚合的方式,而不是使用继承。

    三、Java的23中设计模式

    从这一块开始,我们详细介绍Java中23种设计模式的概念,应用场景等情况,并结合他们的特点及设计模式的原则进行分析。

    1、工厂方法模式(Factory Method)

    工厂方法模式分为三种:

    11、普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:

    举例如下:(我们举一个发送邮件和短信的例子)

    首先,创建二者的共同接口:

    1. public interface Sender {  
    2.     public void Send();  
    3. }  

    其次,创建实现类:

    1. public class MailSender implements Sender {  
    2.     @Override  
    3.     public void Send() {  
    4.         System.out.println("this is mailsender!");  
    5.     }  
    6. }  
    1. public class SmsSender implements Sender {  
    2.   
    3.     @Override  
    4.     public void Send() {  
    5.         System.out.println("this is sms sender!");  
    6.     }  
    7. }  

    最后,建工厂类:

    1. public class SendFactory {  
    2.   
    3.     public Sender produce(String type) {  
    4.         if ("mail".equals(type)) {  
    5.             return new MailSender();  
    6.         } else if ("sms".equals(type)) {  
    7.             return new SmsSender();  
    8.         } else {  
    9.             System.out.println("请输入正确的类型!");  
    10.             return null;  
    11.         }  
    12.     }  
    13. }  

    我们来测试下:

    1. public class FactoryTest {  
    2.   
    3.     public static void main(String[] args) {  
    4.         SendFactory factory = new SendFactory();  
    5.         Sender sender = factory.produce("sms");  
    6.         sender.Send();  
    7.     }  
    8. }  

    输出:this is sms sender!

    22、多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:

    将上面的代码做下修改,改动下SendFactory类就行,如下:

    [java] view plaincopypublic class SendFactory {  
       public Sender produceMail(){  
    1.         return new MailSender();  
    2.     }  
    3.       
    4.     public Sender produceSms(){  
    5.         return new SmsSender();  
    6.     }  
    7. }  

    测试类如下:

    1. public class FactoryTest {  
    2.   
    3.     public static void main(String[] args) {  
    4.         SendFactory factory = new SendFactory();  
    5.         Sender sender = factory.produceMail();  
    6.         sender.Send();  
    7.     }  
    8. }  

    输出:this is mailsender!

    33、静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    1. public class SendFactory {  
    2.       
    3.     public static Sender produceMail(){  
    4.         return new MailSender();  
    5.     }  
    6.       
    7.     public static Sender produceSms(){  
    8.         return new SmsSender();  
    9.     }  
    10. }  
    1. public class FactoryTest {  
    2.   
    3.     public static void main(String[] args) {      
    4.         Sender sender = SendFactory.produceMail();  
    5.         sender.Send();  
    6.     }  
    7. }  

    输出:this is mailsender!

    总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

    2、抽象工厂模式(Abstract Factory)

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。

    请看例子:

    1. public interface Sender {  
    2.     public void Send();  
    3. }  

    两个实现类:

    1. public class MailSender implements Sender {  
    2.     @Override  
    3.     public void Send() {  
    4.         System.out.println("this is mailsender!");  
    5.     }  
    6. }  
    1. public class SmsSender implements Sender {  
    2.   
    3.     @Override  
    4.     public void Send() {  
    5.         System.out.println("this is sms sender!");  
    6.     }  
    7. }  

    两个工厂类:

    1. public class SendMailFactory implements Provider {  
    2.       
    3.     @Override  
    4.     public Sender produce(){  
    5.         return new MailSender();  
    6.     }  
    7. }  
    1. public class SendSmsFactory implements Provider{  
    2.   
    3.     @Override  
    4.     public Sender produce() {  
    5.         return new SmsSender();  
    6.     }  
    7. }  

    在提供一个接口:

    1. public interface Provider {  
    2.     public Sender produce();  
    3. }  

    测试类:

    1. public class Test {  
    2.   
    3.     public static void main(String[] args) {  
    4.         Provider provider = new SendMailFactory();  
    5.         Sender sender = provider.produce();  
    6.         sender.Send();  
    7.     }  
    8. }  

    其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

    3、单例模式(Singleton

    单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

    1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

    2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

    3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

    首先我们写一个简单的单例类:

    1. public class Singleton {  
    2.   
    3.     /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
    4.     private static Singleton instance = null;  
    5.   
    6.     /* 私有构造方法,防止被实例化 */  
    7.     private Singleton() {  
    8.     }  
    9.   
    10.     /* 静态工程方法,创建实例 */  
    11.     public static Singleton getInstance() {  
    12.         if (instance == null) {  
    13.             instance = new Singleton();  
    14.         }  
    15.         return instance;  
    16.     }  
    17.   
    18.     /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */  
    19.     public Object readResolve() {  
    20.         return instance;  
    21.     }  
    22. }  


    这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了,如何解决?我们首先会想到对getInstance方法加synchronized关键字,如下:

    1. public static synchronized Singleton getInstance() {  
    2.         if (instance == null) {  
    3.             instance = new Singleton();  
    展开全文
  • Java常用设计模式详解及其优缺点

    千次阅读 2019-04-15 15:54:51
    简单工厂模式、工厂方法模式、抽象工厂模式、静态代理模式、JDK动态代理模式、cglib动态代理模式、策略模式、模板模式、装饰器模式、观察者模式 简单工厂模式 简单工厂模式又称为静态工厂方法模式,涉及到三个角色...
  • java设计模式(一)---工厂方法模式

    万次阅读 2019-09-25 16:03:12
    基本上有兴趣了解设计模式的都会知道工厂模式,因为各种模式相关的书籍以及博客什么的都是以工厂模式开头的,对于一时兴起或者三天热度的都是会看到工厂模式,但是工厂模式也是用到比较广泛的模式,属于创建型模式。...
  • java程序设计模式_概述

    千次阅读 2019-04-23 12:58:26
    转自:...设计模式 设计模式就是针对某一种特殊场景而给出的标准解决方案,是...
  • Java常用的设计模式

    千次阅读 2019-03-11 09:30:01
    设计模式是编程解决实际问题或类似问题的最佳实践,Java编程中处处都是对象,对象需要创建,对象间需要相互调用,对象的模板是类,类与类需要相互关联引用,如何通用解决上述问题,经过长时间的编程实践总结出来的...
  • Java设计模式常见使用场景

    万次阅读 2020-09-22 08:26:28
    一、Java I/O中的设计模式1、适配器模式适配器模式就是把一个类的接口变换成客户端所能接受的另一种接口,从而使两个接口不匹配而无法在一起工作的两个类能够在一起工作。通常被用在一个项目需要引用一些开源框架来...
  • Java中常用的设计模式

    万次阅读 多人点赞 2019-03-15 17:30:53
    一、什么是设计模式 设计模式(Design pattern)是一套被反复使用、多数人知晓的、... 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块...
  • java常用设计模式总结

    万次阅读 2017-12-24 17:42:14
    掌握常用的几种(最起码单例模式、工厂模式),了解其他的设计模式即可,做到手里有粮,心里不慌。首先,掌握每种模式的定义及使用场景。其次,掌握一个形象的例子,简单的过一遍代码。 学习设计模式的真正目的:...
  • java 23 种设计模式-00-序章 java 23 种设计模式-01-工厂模式(factory) java 23 种设计模式-02-抽象工厂模式(abstract factory) 目录 系列导航索引 目录 设计模式 写在前面 创作缘由 谁适合阅读本系列教程 ...
  • java23种设计模式(最全最详细版)

    万次阅读 2018-09-05 11:53:37
    https://blog.csdn.net/zhangerqing/article/details/8194653
  • Java设计模式》刘伟 超清晰版本 下载链接

    万次阅读 多人点赞 2019-05-07 16:11:58
    本书作者:刘伟 支持正版:链接 PDF下载: 1、GitBook下载 2、百度网盘:https://pan.baidu.com/s/1YEZ4pgOrMPji-KiaZb0giw 密码:gsef 本文参考来源:http://quanke.name/posts/15671/ ......
  • 十年磨一剑——《Java设计模式》正式出版

    万次阅读 多人点赞 2018-03-18 17:09:32
    十年磨一剑,《Java设计模式》于2018年3月正式出版,感谢清华大学出版社和各位的大力支持!笔者自认为该书是国内最好的Java设计模式图书之一!,低调! 本书内容丰富,实例完整,主要特点如下:● 内容丰富,详细...
  • Java面试题内容聚合

    万次阅读 多人点赞 2019-12-04 14:08:10
    这是一份常见Java面试题分类汇总,希望对大家有用! 初级面试题 Java面试题-基础篇一 Java面试题-基础篇二 Java面试题-集合框架篇三 Java面试题-基础篇四 Java面试题-基础篇五 Java面试题-javaweb篇六 ...
  • java设计模式面试题大全含答案

    千次阅读 2019-05-26 01:23:27
    java设计模式面试题大全含答案 1、23种经典设计模式都有哪些,如何分类? 2、j2ee常用的设计模式?说明工厂模式。 3、Spring 框架中都用到了哪些设计模式? 4、《java面试宝典》之java设计模式面试题 5、开发中都...
  • Java - 简述一下你了解的设计模式

    万次阅读 2019-03-17 14:58:51
    所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用...
  • Java模式的秘密--java常用的几种模式

    万次阅读 多人点赞 2017-02-16 13:43:15
    要学习设计模式,首先要明白设计模式,就是为实现某一种或某一组功能提供的代码编码方式.它没有固定的套路,只有约定俗成的风格.所有编码者可以根据已有的设计模式开放思维,设计出自己的设计模式,也会在无意中使用某些...
  • 图解Java设计模式(一)

    万人学习 2019-07-08 11:03:42
    本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式 1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML...
1 2 3 4 5 ... 20
收藏数 665,099
精华内容 266,039
关键字:

java设计模式