zoukankan      html  css  js  c++  java
  • JAVA设计模式简介及八种常见设计模式详解

    一、什么是设计模式                                                                                                                                       

      设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:

      模式:在某些场景下,针对某类问题的某种通用的解决方案。

      场景:项目所在的环境

      问题:约束条件,项目目标等

      解决方案:通用、可复用的设计,解决约束达到目标。

    二、设计模式的六大原则

      因为设计模式就是基于这些原则的实现,所以很有必要了解这些原则,下面主要对面向对象编程的几个原则进行简单介绍。

      1、开闭原则(Open Close Principle)

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

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

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

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

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

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

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

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

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

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

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

    三、设计模式的三个分类                                                                                                                                

      创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。

      结构型模式:把类或对象结合在一起形成一个更大的结构。

      行为型模式:类和对象如何交互,及划分责任和算法。

      如下图所示:

     

    四、各分类中模式的关键点      

      创建型模式                                                                                                            

      单例模式:某个类只能有一个实例,提供一个全局的访问点。

      简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

      工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。

      抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。

      建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。

      原型模式:通过复制现有的实例来创建新的实例。

      结构性模式

      适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。

      组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。

      装饰模式:动态的给对象添加新的功能。

      代理模式:为其他对象提供一个代理以便控制这个对象的访问。

      亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。

      外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。

      桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。

       行为型模式

      模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。

      解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。

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

      状态模式:允许一个对象在其对象内部状态改变时改变它的行为。

      观察者模式:对象间的一对多的依赖关系。

      备忘录模式:在不破坏封装的前提下,保持对象的内部状态。

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

      命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。

      访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。

      责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。

      迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。

    五、八种常见设计模式详解 

      1、单例模式

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

      1.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...");
        }
    }

       1.2、懒汉式

      ——当第一次去使用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. 静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

      2.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.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();
        }
    }

       2.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();
        }
    }

       2.4、抽象工厂模式

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

    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、 适配器设计模式

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

      主要分三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

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

       4.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();
        }
    }

       4.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("
    Circle of red border");
            redCircle.draw();
    
            System.out.println("
    Rectangle 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、 代理模式

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

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

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

       8、模板方法模式

    定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

       需求:简单描述一下:本公司有程序猿、测试、HR、项目经理等人,下面使用模版方法模式,记录下所有人员的上班情况 

      模板方法模式中的三类角色: 

        1、具体方法(Concrete Method) 

        2、抽象方法(Abstract Method) 

        3、钩子方法(Hook Method) 

     // 具体方法
     public final void workOneDay() {
         Log.e("workOneDay", "-----------------work start----------------");
         enterCompany();
         work();
         exitCompany();
         Log.e("workOneDay", "-----------------work end----------------");
     }
     // 工作  抽象方法
     public abstract void work();
     // 钩子方法
     public boolean isNeedPrintDate() {
         return false;
     }
     private void exitCompany() {
         if (isNeedPrintDate()) {
             Log.e("exitCompany", "---" + new Date().toLocaleString() + "--->");
         }
         Log.e("exitCompany", name + "---离开公司");
     }
     /**
      * 重写父类的此方法,使可以查看离开公司时间
      */
     @Override
     public boolean isNeedPrintDate() {
         return true;
     }

     最后测试: 

      查看所有人员的工作情况:

    QAWorker qaWorker = new QAWorker("测试人员");
     qaWorker();
     HRWorker hrWorker = new HRWorker("莉莉姐");
     hrWorker.workOneDay();
    ...
     

       查看程序猿离开公司的时间:

    ITWorker itWorker = new ITWorker("jingbin");
    itWorker.workOneDay();

      

    参考:

      https://www.cnblogs.com/pony1223/p/7608955.html

       https://blog.csdn.net/gfuugff/article/details/86641373?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.channel_param

      https://www.cnblogs.com/Diyo/p/11415588.html

      https://blog.csdn.net/wmq880204/article/details/75106848

  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/liuxiaochong/p/13536467.html
Copyright © 2011-2022 走看看