设计模式 订阅
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 展开全文
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
信息
特    点
每个模式都有各自的名字
别    名
设计模式
分    类
基础模式,委托模式,接口模式等
中文名
软件设计模式
外文名
Design pattern
软件设计模式简介
设计模式(英语 design pattern)是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。这个术语的含义还存有争议。算法不是设计模式,因为算法致力于解决问题而非设计问题。设计模式通常描述了一组相互紧密作用的类与对象。设计模式提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计者掌握。设计模式还为软件重构提供了目标。随着软件开发社群对设计模式的兴趣日益增长,已经出版了一些相关的专著,定期召开相应的研讨会,而且Ward Cunningham为此发明了WikiWiki用来交流设计模式的经验。
收起全文
精华内容
下载资源
问答
  • JAVA设计模式之单例模式

    万次阅读 多人点赞 2014-04-16 06:51:34
    本文继续介绍23种设计模式系列之单例模式。 概念:  java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类...

    本文继续介绍23种设计模式系列之单例模式。

    概念:
      java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
      单例模式有以下特点:
      1、单例类只能有一个实例。
      2、单例类必须自己创建自己的唯一实例。
      3、单例类必须给所有其他对象提供这一实例。
      单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。


    一、懒汉式单例

     

    //懒汉式单例类.在第一次调用的时候实例化自己 
    public class Singleton {
        private Singleton() {}
        private static Singleton single=null;
        //静态工厂方法 
        public static Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
        }
    }

     

    Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

    (事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

    但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题:

     

    1、在getInstance方法上加同步

     

    public static synchronized Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
    }

     

     

     

    2、双重检查锁定

     

    public static Singleton getInstance() {
            if (singleton == null) {  
                synchronized (Singleton.class) {  
                   if (singleton == null) {  
                      singleton = new Singleton(); 
                   }  
                }  
            }  
            return singleton; 
        }

     

    3、静态内部类

     

    public class Singleton {  
        private static class LazyHolder {  
           private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
           return LazyHolder.INSTANCE;  
        }  
    }  

    这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

     

     

     

     

     

     

    二、饿汉式单例

     

    //饿汉式单例类.在类初始化时,已经自行实例化 
    public class Singleton1 {
        private Singleton1() {}
        private static final Singleton1 single = new Singleton1();
        //静态工厂方法 
        public static Singleton1 getInstance() {
            return single;
        }
    }

    饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

     

     

     

     

    三、登记式单例(可忽略)

    //类似Spring里面的方法,将类名注册,下次从里面直接获取。
    public class Singleton3 {
        private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
        static{
            Singleton3 single = new Singleton3();
            map.put(single.getClass().getName(), single);
        }
        //保护的默认构造子
        protected Singleton3(){}
        //静态工厂方法,返还此类惟一的实例
        public static Singleton3 getInstance(String name) {
            if(name == null) {
                name = Singleton3.class.getName();
                System.out.println("name == null"+"--->name="+name);
            }
            if(map.get(name) == null) {
                try {
                    map.put(name, (Singleton3) Class.forName(name).newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            return map.get(name);
        }
        //一个示意性的商业方法
        public String about() {    
            return "Hello, I am RegSingleton.";    
        }    
        public static void main(String[] args) {
            Singleton3 single3 = Singleton3.getInstance(null);
            System.out.println(single3.about());
        }
    }

     登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。 

    这里我对登记式单例标记了可忽略,我的理解来说,首先它用的比较少,另外其实内部实现还是用的饿汉式单例,因为其中的static方法块,它的单例在类被装载的时候就被实例化了。

     

    饿汉式和懒汉式区别

    从名字上来说,饿汉和懒汉,

    饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,

    而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。

    另外从以下两点再区分以下这两种方式:

     

    1、线程安全:

    饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

    懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。


     

    2、资源加载和性能:

    饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,

    而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

    至于1、2、3这三种实现又有些区别,

    第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,

    第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗

    第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。

     

    什么是线程安全?

    如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

    或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

     

    应用

    以下是一个单例类使用的例子,以懒汉式为例,这里为了保证线程安全,使用了双重检查锁定的方式:

     

    public class TestSingleton {
    	String name = null;
    
            private TestSingleton() {
    	}
    
    	private static volatile TestSingleton instance = null;
    
    	public static TestSingleton getInstance() {
               if (instance == null) {  
                 synchronized (TestSingleton.class) {  
                    if (instance == null) {  
                       instance = new TestSingleton(); 
                    }  
                 }  
               } 
               return instance;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public void printInfo() {
    		System.out.println("the name is " + name);
    	}
    
    }

    可以看到里面加了volatile关键字来声明单例对象,既然synchronized已经起到了多线程下原子性、有序性、可见性的作用,为什么还要加volatile呢,原因已经在下面评论中提到,

    还有疑问可参考http://www.iteye.com/topic/652440
    和http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

     

     

     

    public class TMain {
    	public static void main(String[] args){
    		TestStream ts1 = TestSingleton.getInstance();
    		ts1.setName("jason");
    		TestStream ts2 = TestSingleton.getInstance();
    		ts2.setName("0539");
    		
    		ts1.printInfo();
    		ts2.printInfo();
    		
    		if(ts1 == ts2){
    			System.out.println("创建的是同一个实例");
    		}else{
    			System.out.println("创建的不是同一个实例");
    		}
    	}
    }
    

     运行结果:

    结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。

    对于单例模式的几种实现方式,知道饿汉式和懒汉式的区别,线程安全,资源加载的时机,还有懒汉式为了实现线程安全的3种方式的细微差别。

    更多设计模式:23种设计模式系列

    作者:jason0539

    博客:http://blog.csdn.net/jason0539(转载请说明出处)

    展开全文
  • 常用设计模式总结

    万次阅读 多人点赞 2019-07-31 19:13:12
    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,是可复用面向对象软件的基础。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 ...

    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,是可复用面向对象软件的基础。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。java设计模式广泛认同的有23种,本文介绍最常用的、最会被问到的设计模式。
    #一、设计模式的分类
    总体来说23种设计模式分为三大类:
    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    #二、设计模式的六大原则
    总原则-开闭原则
    对扩展开放,对修改封闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。
    想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。
    1、单一职责原则
    不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分。
    2、里氏替换原则(Liskov Substitution Principle)
    任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
    里氏代换原则是对“开-闭”原则的补充。实现“开闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
    3、依赖倒转原则(Dependence Inversion Principle)
    面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
    4、接口隔离原则(Interface Segregation Principle)
    每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
    5、迪米特法则(最少知道原则)(Demeter Principle)
    一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
    最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
    6、合成复用原则(Composite Reuse Principle)
    尽量首先使用合成/聚合的方式,而不是使用继承。
    #常用设计模式
    ##1、工厂方法模式
    工厂方法模式分为三种:
    1.1、普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
    举例如下:(我们举一个发送邮件和短信的例子)

    public interface Sender {  
        public void Send();  
    }  
    public class MailSender implements Sender {  
        @Override  
        public void Send() {  
            System.out.println("this is mailsender!");  
        }  
    }  
    public class SmsSender implements Sender {  
      
        @Override  
        public void Send() {  
            System.out.println("this is sms sender!");  
        }  
    }  
    public class SendFactory {  
      
        public Sender produce(String type) {  
            if ("mail".equals(type)) {  
                return new MailSender();  
            } else if ("sms".equals(type)) {  
                return new SmsSender();  
            } else {  
                System.out.println("请输入正确的类型!");  
                return null;  
            }  
        }  
    }  
    public class FactoryTest {  
      
        public static void main(String[] args) {  
            SendFactory factory = new SendFactory();  
            Sender sender = factory.produce("sms");  
            sender.Send();  
        }  
    }  
    

    输出:this is sms sender!
    2.2、多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
    将上面的代码做下修改,改动下SendFactory类就行,如下:

    public class SendFactory {  
          
        public Sender produceMail(){  
            return new MailSender();  
        }  
          
        public Sender produceSms(){  
            return new SmsSender();  
        }  
    }  
    public class FactoryTest {  
      
        public static void main(String[] args) {  
            SendFactory factory = new SendFactory();  
            Sender sender = factory.produceMail();  
            sender.Send();  
        }  
    }  
    

    输出:this is mailsender!
    3.3、静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    public class SendFactory {  
          
        public static Sender produceMail(){  
            return new MailSender();  
        }  
          
        public static Sender produceSms(){  
            return new SmsSender();  
        }  
    }  
    public class FactoryTest {  
      
        public static void main(String[] args) {      
            Sender sender = SendFactory.produceMail();  
            sender.Send();  
        }  
    }  
    

    输出:this is mailsender!
    总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。
    ##2、抽象工厂模式
    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

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

    其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!
    ##3、单例模式
    java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍经常被面试的经典的两种:懒汉模式、饿汉模式。
    单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。比如每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。
    ###3.1、懒汉式单例

    //懒汉式单例类.在第一次调用的时候实例化自己 
    public class Singleton {
        private Singleton() {}
        private static Singleton single=null;
        //静态工厂方法 
        public static Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
        }
    } 
    

    Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。
    (事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)
    但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全。
    1、在getInstance方法上加同步

    public static synchronized Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
    }
    

    2、双重检查锁定

    public static Singleton getInstance() {
            if (singleton == null) {  
                synchronized (Singleton.class) {  
                   if (singleton == null) {  
                      singleton = new Singleton(); 
                   }  
                }  
            }  
            return singleton; 
    }
    

    3、静态内部类

    public class Singleton {  
        private static class LazyHolder {  
           private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
           return LazyHolder.INSTANCE;  
        }  
    }  
    

    这种方式是当被调用getInstance()时才去加载静态内部类LazyHolder,LazyHolder在加载过程中会实例化一个静态的Singleton,因为利用了classloader的机制来保证初始化instance时只有一个线程,所以Singleton肯定只有一个,是线程安全的,这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

    ###3.2、饿汉式单例

    //饿汉式单例类.在类初始化时,已经自行实例化 
    public class Singleton1 {
        private Singleton1() {}
        private static final Singleton1 single = new Singleton1();
        //静态工厂方法 
        public static Singleton1 getInstance() {
            return single;
        }
    }
    

    饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

    ###3.3、饿汉式和懒汉式区别
    从名字上来说,饿汉和懒汉,
    饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,
    而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
    另外从以下两点再区分以下这两种方式:
    1、线程安全:
    饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
    懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。
    2、资源加载和性能:
    饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,
    而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
    至于1、2、3这三种实现又有些区别,
    第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,
    第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
    第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。
    综上大部分情况下单例模式中最好的实现方式就是静态内部类的懒汉模式。
    ##4、建造者模式
    一、场景
    当需要生产一辆汽车时,我们需要为其装配发动机、轮胎、座椅等等部件,这个装配过程是比较复杂的而且也需要较高的组装技术。而建造者模式(Builder Pattern)就是为了将部件与组装分离开。
    二、 概念
      将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
      与抽象工厂的区别:在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。
      建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。
    三、建造者模式结构组成
    Product: 表示被构造的复杂对象,其中包含需要构建的部件属性。
    Builder: 创建一个产品对象的各个部件指定抽象接口。
    ConcreteBuilder: 实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示。
    Director: 调用具体建造者角色以创建产品对象。
    下面以构建一辆汽车为例,写示例代码:
    1.Product角色:组装一辆汽车首先的有各种配件,如发动机、轮胎、座椅等。

    public class Car{
        public String engine;
        public String tyre;
        public String seat;
        public Car(){
    
        }
    
        public String getEngine() {
            return engine;
        }
        public void setEngine(String engine) {
            this.engine = engine;
        }
        public String getTyre() {
            return tyre;
        }
        public void setTyre(String tyre) {
            this.tyre = tyre;
        }
        public String getSeat() {
            return seat;
        }
        public void setSeat(String seat) {
            this.seat = seat;
        }
    
    }
    

    2.Builder角色:知道了所需配件后,就需要生产配件了,定义一个生产配件的抽象建造者接口。

    public interface Builder {
        String buildEngine();
        String buildTyre();
        String buildSeat();
    }  
    

    3.ConcreteBuilder角色:实现抽象的 建造者接口生成具体的建造者,并开始生产具体的配件。

    public class CarBuilder implements Builder{
    
        @Override
        public String buildEngine() {
            // 生产发动机
            return "发动机";
        }
    
        @Override
        public String buildTyre() {
            // 生产轮胎
            return "轮胎";
        }
    
        @Override
        public String buildSeat() {
            // 生产座椅
            return "座椅";
        }
    }
    
    }   
    

    4.Director角色:在生产出配件后,由指导者指导组装配件生成汽车。

    public class CarDirector {
        CarBuilder cb;
        public CarDirector(CarBuilder cb){
            this.cb=cb;
        }
        public Car constructCar(){
            Car car=new Car();
            car.setEngine(cb.buildEngine());
            car.setTyre(cb.buildTyre());
            car.setSeat(cb.buildSeat());
            return car;
        }
    }
    

    5.最终得到一辆汽车:

    public class Client {
    
        public static void main(String[] args) {
            CarDirector carDirector=new CarDirector(new CarBuilder());
            Car car=carDirector.constructCar();
            System.out.println(car.getEngine()+car.getTyre()+car.getSeat());
    
        }
    }
    

    ##5、适配器模式
    适配器模式,把一个类接口变化成客户端所期待的另一个类的接口,使原来因接口不匹配而无法一起工作的类能够一起工作。Java源码中的例子:如Java IO中的java.io.InputStreamReader(InputStream) 和java.io.OutputStreamWriter(OutputStream)就是典型的适配器模式,通过InputStreamReader、OutputStreamWriter适配器将字节流转换为字符流。
    ###5.1、类适配器
    Target(目标角色): 客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
    Adaptee(源角色):现在需要适配的类。
    Adapter(适配器): 适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

    /**
     * 目标角色,如举例中需要转换成的三相插头
     *  @author  14501_000
     */
    public interface Target {
         void handleReq();
    }   
    
    /**
     * 源角色,需要被适配的类,如举例中的两脚插头
     */
    public class Adaptee {
         public void request(){
            System.out.println( "可以完成客户请求的需要的功能!" );
        }
    }   
    
    /**
     * 适配器,把源接口转换成目标接口,即将两脚插头转换为三脚插头
     *
     */
    public class Adapter extends Adaptee implements Target{
         public void handleReq() {
             super.request();
        }
         }   
    
    /**
     * 客户端类,通过三脚插座进行工作
     *
     */
    public class Client {
         public void work(Target t){
             t.handleReq();
        }
         public static void main(String[] args){
            Client c = new Client();
            Target t = new Adapter();
             c.work(t);
        }
    }
    

    ###5.2、对象适配器
    上面这种实现的适配器称为类适配器,因为 Adapter 类既继承了 Adaptee (被适配类),也实现了 Target 接口(因为 Java 不支持多继承,所以这样来实现),在 Client 类中我们可以根据需要选择并创建任一种符合需求的子类,来实现具体功能。另外一种适配器模式是对象适配器,它不是使用多继承或继承再实现的方式,而是使用直接关联,或者称为委托的方式,通过组合的方式跟适配对象组合。

    /**
     * 适配器,把源接口转换成目标接口,即将两脚插头转换为三脚插头
     *
     */
    public class Adapter implements Target{
        Adaptee adaptee ;
         public Adapter(Adaptee adaptee){
             this.adaptee = adaptee ;
        }
         public void handleReq() {
             adaptee.request();
        }
    
    }
    
    public class Client {
         public void work(Target  t){
             t.handleReq();
        }
         public static void main(String[]  args ) {
            Client c =new Client();
            Adaptee adaptee =new Adaptee();
            Target t = new Adapter(adaptee);
             c.work( t );
        }
    }
    

    测试结果与上面的一致。 使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。
    ###5.3、适配器模式适用场景
    系统需要使用现有的类,而这些类的接口不符合系统的接口。
    想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
    两个类所做的事情相同或相似,但是具有不同接口的时候。
    旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。
    ##6、装饰者模式
    装饰(Decorate)模式又称为包装(Wrapper)模式。可以动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
    举一个简单的汽车例子,创造每一种功能的汽车都需要继承车的父类进行实现,那么当我们需要既能路上行驶又能水上行驶的车又得继续继承父类拓展新的类。所以每增加一种新功能的汽车都需要新增一个类,这样的话就会创建大量的类。这时候就能使用装饰模式了。
    ###6.1、示例
    抽象构件

    public interface AbstractCar {
        void move();
    }  
    

    具体构建

    public class Car implements AbstractCar{
    
        public void move() {
            System.out.println("路上行驶");
        }
    }
    

    装饰角色

    public class SuperCar implements AbstractCar{
        protected AbstractCar car;
        public SuperCar(AbstractCar car){
            this.car=car;
        }
    
        public void move() {
            car.move();
        }
    
    }
    

    具体装饰 角色

    /**
     * 飞行汽车  
    */   
    
    ublic class FlyCar extends SuperCar{
    
        public FlyCar(AbstractCar car) {
            super(car);
        }
    
        public void fly() {
            System.out.println("空中行驶汽车");
        }
    
    
        @Override
        public void move() {
            super.move();
             fly();
        }
    
    }
    
    
    
    /**
     * 水上汽车
     */
    public class WaterCar extends SuperCar{
    
        public WaterCar(AbstractCar car) {
            super(car);
        }
    
        public void swim() {
            System.out.println("水上行驶汽车");
        }
        @Override
        public void move() {
            super.move();
            swim();
        }
    
    }
    

    客户端

    public class Client {
    
        public static void main(String[] args) {
            Car car=new Car();
            car.move();
    
            System.out.println("------增加新功能,飞行------");
            FlyCar flyCar=new FlyCar(car);
            flyCar.move();
    
            System.out.println("------新增加功能,水上行驶-----");
            WaterCar waterCar=new WaterCar(car);
            waterCar.move();
    
            System.out.println("-----新增加两个功能,飞行与水上行驶-----");
            WaterCar waterCar2=new WaterCar(flyCar);
            waterCar2.move();
    
        }
    
    }
    

    //输出结果
    路上行驶
    ------增加新功能,飞行------
    路上行驶
    空中行驶汽车
    ------新增加功能,水上行驶-----
    路上行驶
    水上行驶汽车
    -----新增加两个功能,飞行与水上行驶-----
    路上行驶
    空中行驶汽车
    水上行驶汽车
    由此可知,使用装饰模式就不用创建大量新的类而可以拓展出具有更多功能的对象了。
    ###6.2、装饰模式在Java I/O库中的应用
    IO流实现细节:
    Component抽象构件角色:io流中的InputStream,OutputStream,Reader,Writer
    ConcreteComponent具体构件角色:io流中的FileInputStream,FileOutputStream
    Decorate装饰角色:持有抽象构件的引用,FilterInputStream,FilterOutputStream
    ConcreteDecorate具体装饰角色:负责给构件对象添加新的责任,BufferedInputStream,BufferedOutputStream等
    ##7、代理模式
    为某个对象提供一个代理,从而控制这个代理的访问。代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代。代理类负责请求的预处理、过滤、将请求分配给委托类处理、以及委托类处理完请求的后续处理。
    ###7.1、静态代理
    由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
    示例代码:
    1.抽象角色

    public interface AbstractSubject {
         void doSomething();
    }   
    

    2.代理角色

    public class ProxySubject implements AbstractSubject{
         private AbstractSubject  real ;
         public ProxySubject(AbstractSubject  real) {
             this.real=real ;
        }
         @Override
         public void doSomething() {
    
             real.doSomething();
        }
    
         public void doOtherthing() {
    
        }
    }   
    

    3.真实角色

    public class RealSubject implements AbstractSubject{
         @Override
         public void doSomething() {
            System.out.println( "真实角色被使用" );
        }
    }   
    

    4.客户端

    public class Client {
         public static void main(String[]  args ) {
            RealSubject real = new  RealSubject();
            ProxySubject proxy = new  ProxySubject( real );
             proxy.doSomething();
        }
    }   
    

    5.静态代理的优缺点
    优点: 业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
    缺点:代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
    ###7.2、动态代理
    动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件。代理角色和真实角色的联系在程序运行时确定。
    1.首先看看和动态代理相关JavaAPI
    ① .java.lang.reflect.Proxy
    这是Java动态代理机制生成的所有代理类的父类,它提供了一组静态的方法来为一组接口动态的生成代理类及其对象。
    Proxy类的静态方法:

    //方法 1: 该方法用于获取指定代理对象所关联的调用处理器  
    static InvocationHandler getInvocationHandler(Object proxy )  
    //方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象  
    static Class getProxyClass(ClassLoader loader,Class[] interfaces)  
    //方法 3:该方法用于判断指定类对象是否是一个动态代理类  
    static boolean isProxyClass(Class cl )    
    //方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
    static Object newProxyInstance(ClassLoader loader,  Class[] interfaces, InvocationHandler  h )   
    

    ②.java.lang.reflect.InvocationHandler
    这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。
    InvocationHandler核心方法

    //该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象  
    //第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行   
    Object invoke(Object proxy, Method  method,Object[] args )     
    

    ③ .java.lang.reflect.ClassLoader
      这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。每次生成动态代理类对象时都需要指定一个类装载器对象 。
    2.动态代理实现步骤

    • 实现InvocationHandler接口创建自己的调用处理器 。
    • 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类 。
    • 执行真实角色具体任务。

    示例代码
    1.抽象角色和真实角色代码与上述相同 。
    2. 创建自己的调用处理器:

    public class SubjectHandler implements InvocationHandler{
        AbstractSubject real;
        public SubjectHandler(AbstractSubject real){
            this.real=real;
        }
    
        @Override
        public Object invoke(Object obj, Method method, Object[] args)throws Throwable {
            System.out.println("代理类预处理任务");
            //利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。  
      //因为示例程序没有返回值,所以这里忽略了返回值处理
            method.invoke(real, args);
            System.out.println("代理类后续处理任务");
            return null;
        }
    
    }
    

    3.客户端 :

    public class Client {
    
        public static void main(String[] args) {
            RealSubject real=new RealSubject();
            SubjectHandler handler=new SubjectHandler(real);
            //生成代理类对象
            AbstractSubject proxy=(AbstractSubject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{AbstractSubject.class},handler);
            proxy.doSomething();
    
        }
    
    }
    

    4.动态代理的优缺点
    优点:
      动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
    不足:
      Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。
    ##8、策略模式
    下面是某个市场人员接到单后的报价策略,报价策略很复杂,可以简单作如下分类:
    普通客户小批量,不打折
    普通客户大 批量,打9折
    老 客户小批量,打8.5折
    老 客户大批量,打8折
    我们通常可以适用条件语句进行处理,代码如下:

    public class Test {
        public double getPrice(String type ,double price ){
            if(type.equals("普通客户小批量")){
                System.out.println("不打折");
                return price;
            }else if(type.equals("普通客户大批量")){
                System.out.println("打9折");
                return price*0.9;
    
            }else if(type.equals("老客户小批量")){
                System.out.println("打8.5折");
                return price*0.85;
    
            }else if(type.equals("老客户大批量")){
                System.out.println("打8折");
                return price*0.8;
            }
            return price;
        }
    }
    

    这样实现起来比较简单,符合一般开人员的思路,但是当类型特别多,算法比较复杂时,整个条件控制代码会变得很长,难于维护。这时我们可以采用策略模式,将不同的策略分开,委派给不同的对象管理。
    使用策略模式实现:

    public interface Strategy {
        /**
         * 
         * @param price 商品原价
         * @return 打折后价格
         */
        public double getPrice(double price);
    }
    
    
    public class NewCustomerFewStrategy implements Strategy{
    
        public double getPrice(double price) {
            System.out.println("普通客户小批量,不打折");
            return price;
        }
    }
    
    public class NewCustomerManyStrategy implements Strategy{
    
        public double getPrice(double price) {
            System.out.println("普通客户大批量,打9折");
            return price*0.9;
        }
    }
    
    public class OldCustomerFewStrategy implements Strategy{
    
        public double getPrice(double price) {
            System.out.println("老客户小批量,打8.5折");
            return price*0.85;
        }
    }
    
    public class OldCustomerManyStrategy implements Strategy{
    
        public double getPrice(double price) {
            System.out.println("老客户大批量,打8折");
            return price;
        }
    } 
    
    
    public class Context {
        private Strategy strategy;//持有策略引用
    
        public Context(Strategy strategy) {
            super();
            this.strategy = strategy;
        }
        public void printPrice(double price ){
            System.out.println("价格为:"+strategy.getPrice(price));
        }
    }
    
    
    
    public class Client {
         public static void main(String[] args) {
            Strategy strategy= new NewCustomerFewStrategy();
            Context context= new Context(strategy);
            context.printPrice(100);
        }
    
    }  
    
    //输出结果
    //普通客户小批量,不打折
    //价格为:100.0  
    
    

    从上面的示例可以看出,策略模式仅仅封装算法,提供新的算法插入到已有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定在何时使用何种算法。在什么情况下使用什么算法是由客户端决定的。
    优点:
    策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
    使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
    缺点:
    客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
    由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
    ##9、模板方法模式
    模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。
    比如定义一个操作中的算法的骨架,将步骤延迟到子类中。模板方法使得子类能够不去改变一个算法的结构即可重定义算法的某些特定步骤。
    模式中的角色:

    • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。
    • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

    以准备去学校所要做的工作(prepareGotoSchool)为例,假设需要分三步:穿衣服(dressUp),吃早饭(eatBreakfast),带上东西(takeThings)。学生和老师要做得具体事情肯定有所区别。
    抽象类AbstractClass

    public abstract class AbstractPerson{  
         //抽象类定义整个流程骨架  
         public void prepareGotoSchool(){  
              dressUp();  
              eatBreakfast();  
              takeThings();  
         }  
         //以下是不同子类根据自身特性完成的具体步骤  
         protected abstract void dressUp();  
         protected abstract void eatBreakfast();  
         protected abstract void takeThings();  
    } 
    

    具体类ConcreteClass

    public class Student extends AbstractPerson{  
         @Override  
         protected void dressUp() {  
              System.out.println(“穿校服");  
         }  
         @Override  
         protected void eatBreakfast() {  
              System.out.println(“吃妈妈做好的早饭");  
         }  
      
         @Override  
         protected void takeThings() {  
              System.out.println(“背书包,带上家庭作业和红领巾");  
         }  
    }  
    
    public class Teacher extends AbstractPerson{  
         @Override  
         protected void dressUp() {  
              System.out.println(“穿工作服");  
         }  
         @Override  
         protected void eatBreakfast() {  
              System.out.println(“做早饭,照顾孩子吃早饭");  
         }  
      
         @Override  
         protected void takeThings() {  
              System.out.println(“带上昨晚准备的考卷");  
         }  
    }  
    
    public class Client {  
         public static void main(String[] args) {  
         Student student = new Student()  
         student.prepareGotoSchool();  
      
         Teacher teacher  = new Teacher()  
         teacher.prepareGotoSchool();  
         }  
    }  
    

    优点:
    模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。
    子类实现算法的某些细节,有助于算法的扩展。
    通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
    缺点:
    每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
    适用场景:
    在某些类的算法中,用了相同的方法,造成代码的重复。
    控制子类扩展,子类必须遵守算法规则。
    ##10、观察者模式
    观察者模式定义了一个一对多的依赖关系,让多个观察者对象同时监听同一个主题对象。当这个主题状态发生改变时,会通知所有观察者对象,让它们自动更新自己。
    ###10.1、模型结构

    • 抽象主题角色(Subject): 把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
    • 具体主题角色(ConcreteSubject): 在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
    • 抽象观察者角色(Observer): 为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
    • 具体观察者角色(ConcreteObserver): 该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
      这里写图片描述

    ###10.2、代码示例
    抽象主题角色:

    public class Subject {
        protected List<Observer> list=new ArrayList<Observer>();
    
        public void registerObserve(Observer obs){
            list.add(obs);
        }
    
        public void removeObserve(Observer obs){
            list.remove(obs);
        }
    
        //通知所有的观察者更新状态
        public void notifyAllObserve(){
            for(Observer obs:list){
                obs.update(this);
            }
        }
    }
    

    具体 主题角色:

    public class ConcreteSubject extends Subject{
        private int state;
    
        public int getState() {
            return state;
        }
    
        //主题对象发生变化,通知所有观察者
        public void setState(int state) {
            this.state = state;
            this.notifyAllObserve();
        }
    }
    

    抽象观察者角色:

    public interface Observer {
        void update(Subject sub);
    }
    

    具体观察者角色:

    public class ConcreteObserver implements Observer{
        private int myState;//与目标对象state值保持一致
    
        public void update(Subject sub) {
            myState=((ConcreteSubject)sub).getState();
            System.out.println("观察者得到的值:"+myState);
        }
    }  
    

    客户端 :

    public class Client {
    
        public static void main(String[] args) {
            //目标对象
            ConcreteSubject cs=new ConcreteSubject();
    
            //创建多个具体观察者
            ConcreteObserver observe1=new ConcreteObserver();
            ConcreteObserver observe2=new ConcreteObserver();
            ConcreteObserver observe3=new ConcreteObserver();
    
            //注册观察者
            cs.registerObserve(observe1);
            cs.registerObserve(observe2);
            cs.registerObserve(observe3);
    
            //改变被观察者状态
            cs.setState(2);
    
        }
    }
    

    输出结果
    观察者得到的值:2
    观察者得到的值:2
    观察者得到的值:2
    ###10.3、推模式与拉模式
    推模式:每次都会把通知以广播的方式发送给所有观察者,所有观察者只能被动接收, 推送的信息通常是主题对象的全部或部分数据 。
    拉模式: 主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过update()方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了 。
    比较: 推模式是假定主题对象知道观察者需要的数据;而拉模式是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
    ###10.4、Java自带对观察者模式的支持
    JavaSE中提供了java.util.Observable和java.util.Observer来实现观察者模式。
    代码示例:
    具体目标对象:

    public class ConcreteSubject extends Observable{
        private int state;
    
        public int getState() {
            return state;
        }
        public void setState(int state) {
            this.state = state;//目标对象状态发生改变
    
            setChanged();//表示目标对象已经做了更改
            notifyObservers(state);//通知所有观察者
        }
    }
    1
    2
    3
    4
    

    具体观察者:

    public class ConcreteObserver implements Observer{
        private int mystate;
        public void update(Observable o, Object arg) {
            mystate=((ConcreteSubject)o).getState();
            System.out.println("观察者接收到的状态:"+mystate);
        }
    }  
    

    客户端:

    public class Client {
        public static void main(String[] args) {
            //创建具体主题
            ConcreteSubject cs=new ConcreteSubject();
    
            //创建观察者
            ConcreteObserver observer1=new ConcreteObserver();
            ConcreteObserver observer2=new ConcreteObserver();
            ConcreteObserver observer3=new ConcreteObserver();
    
            //将观察者加入到目标对象观察者集合
            cs.addObserver(observer1);
            cs.addObserver(observer2);
            cs.addObserver(observer3);
    
            //目标对象改变
            cs.setState(100);
        }
    }
    

    输出结果:
    观察者接收到的状态:100
    观察者接收到的状态:100
    观察者接收到的状态:100


    上面的内容借鉴了很多博主的文章

    展开全文
  • 史上最全设计模式导学目录(完整版)

    万次阅读 多人点赞 2013-12-24 23:15:16
    2012年-2013年,Sunny在CSDN技术博客中陆续发表了100多篇与设计模式相关的文章,涵盖了七个面向对象设计原则和24个设计模式(23个GoF设计模式 + 简单工厂模式),为了方便大家学习,现将所有与设计模式学习相关文章...

       圣诞献礼!   

           2012年-2013年,Sunny在CSDN技术博客中陆续发表了100多篇与设计模式学习相关的文章,涵盖了七个面向对象设计原则和24个设计模式(23个GoF设计模式 +  简单工厂模式,为了方便大家学习,现将所有文章的链接进行了整理,希望能给各位带来帮助!

           祝大家圣诞节快乐! 花絮:本文的工作量大大超过之前的估计,几乎整个平安夜都花在它身上了,

     

    基础知识

     

    设计模式概述

    从招式与内功谈起——设计模式概述(一):设计模式从何而来?

    从招式与内功谈起——设计模式概述(二):设计模式是什么?

    从招式与内功谈起——设计模式概述(三):设计模式有什么用?附:个人观点

     

    面向对象设计原则

    面向对象设计原则概述

    面向对象设计原则之单一职责原则

    面向对象设计原则之开闭原则

    面向对象设计原则之里氏代换原则

    面向对象设计原则之依赖倒转原则

    面向对象设计原则之接口隔离原则

    面向对象设计原则之合成复用原则

    面向对象设计原则之迪米特法则

     

    六个创建型模式

     

    简单工厂模-Simple Factory Pattern【学习难度:★★☆☆☆,使用频率:★★★☆☆

    工厂三兄弟之简单工厂模式(一):图表库的设计

    工厂三兄弟之简单工厂模式(二):简单工厂模式概述

    工厂三兄弟之简单工厂模式(三):图表库的简单工厂模式解决方案

    工厂三兄弟之简单工厂模式(四):图表库解决方案的改进,简单工厂模式的简化,简单工厂模式总结

     

    工厂方法模式-Factory Method Pattern【学习难度:★★☆☆☆,使用频率:★★★★★

    工厂三兄弟之工厂方法模式(一):日志记录器的设计

    工厂三兄弟之工厂方法模式(二):工厂方法模式概述

    工厂三兄弟之工厂方法模式(三):日志记录器的工厂方法模式解决方案,反射与配置文件

    工厂三兄弟之工厂方法模式(四):重载的工厂方法,工厂方法的隐藏,工厂方法模式总结

     

    抽象工厂模式-Abstract  Factory Pattern【学习难度:★★★★☆,使用频率:★★★★★

    工厂三兄弟之抽象工厂模式(一):界面皮肤库的初始设计

    工厂三兄弟之抽象工厂模式(二):产品等级结构与产品族

    工厂三兄弟之抽象工厂模式(三):抽象工厂模式概述

    工厂三兄弟之抽象工厂模式(四):界面皮肤库的抽象工厂模式解决方案

    工厂三兄弟之抽象工厂模式(五):“开闭原则”的倾斜性,抽象工厂模式总结

     

    单例模式-Singleton Pattern【学习难度:★☆☆☆☆,使用频率:★★★★☆

    确保对象的唯一性——单例模式 (一):单例模式的动机,单例模式概述

    确保对象的唯一性——单例模式 (二):负载均衡器的设计与实现

    确保对象的唯一性——单例模式 (三):饿汉式单例与懒汉式单例的讨论

    确保对象的唯一性——单例模式 (四):一种更好的单例实现方法(静态内部类)

    确保对象的唯一性——单例模式 (五):单例模式总结

     

    原型模式-Prototype Pattern【学习难度:★★★☆☆,使用频率:★★★☆☆

    对象的克隆——原型模式(一):大同小异的工作周报,原型模式概述

    对象的克隆——原型模式(二):工作周报的原型模式解决方案

    对象的克隆——原型模式(三):带附件的周报【浅克隆,深克隆】

    对象的克隆——原型模式(四):原型管理器的引入和实现,原型模式总结

     

    建造者模式-Builder Pattern【学习难度:★★★★☆,使用频率:★★☆☆☆

    复杂对象的组装与创建——建造者模式(一):游戏角色设计,建造者模式概述

    复杂对象的组装与创建——建造者模式(二):游戏角色设计的建造者模式解决方案

    复杂对象的组装与创建——建造者模式(三):关于Director的进一步讨论,建造者模式总结

     

     

    七个结构型模式

     

    适配器模式-Adapter Pattern【学习难度:★★☆☆☆,使用频率:★★★★☆

     

    不兼容结构的协调——适配器模式(一):没有源码的算法库,适配器模式概述

    不兼容结构的协调——适配器模式(二):没有源码的算法库的适配器模式解决方案

    不兼容结构的协调——适配器模式(三):类适配器,双向适配器

    不兼容结构的协调——适配器模式(四):缺省适配器,适配器模式总结

     

    桥接模式-Bridge Pattern【学习难度:★★★☆☆,使用频率:★★★☆☆

    处理多维度变化——桥接模式(一):跨平台图像浏览系统

    处理多维度变化——桥接模式(二):桥接模式概述

    处理多维度变化——桥接模式(三):跨平台图像浏览系统的桥接模式解决方案

    处理多维度变化——桥接模式(四):适配器模式与桥接模式的联用,桥接模式总结

     

    组合模式-Composite Pattern【学习难度:★★★☆☆,使用频率:★★★★☆

    树形结构的处理——组合模式(一):设计杀毒软件的框架结构

    树形结构的处理——组合模式(二):组合模式概述

    树形结构的处理——组合模式(三):杀毒软件的框架结构的组合模式解决方案

    树形结构的处理——组合模式(四):透明组合模式与安全组合模式

    树形结构的处理——组合模式(五):公司组织结构,组合模式总结

     

    装饰模式-Decorator Pattern【学习难度:★★★☆☆,使用频率:★★★☆☆

    扩展系统功能——装饰模式(一):图形界面构件库的设计

    扩展系统功能——装饰模式(二):装饰模式概述

    扩展系统功能——装饰模式(三):图形界面构件库的装饰模式解决方案

    扩展系统功能——装饰模式(四):透明装饰模式与半透明装饰模式,装饰模式注意事项,装饰模式总结

     

    外观模式-Facade Pattern【学习难度:★☆☆☆☆,使用频率:★★★★★

    深入浅出外观模式(一):外观模式概述,外观模式结构与实现

    深入浅出外观模式(二):外观模式应用实例(文件加密模块)

    深入浅出外观模式(三):抽象外观类,外观模式效果与适用场景

     

    享元模式-Flyweight Pattern【学习难度:★★★★☆,使用频率:★☆☆☆☆

    实现对象的复用——享元模式(一):围棋棋子的设计,享元模式概述(上)

    实现对象的复用——享元模式(二):享元模式概述(下)

    实现对象的复用——享元模式(三):围棋棋子的享元模式解决方案

    实现对象的复用——享元模式(四):带外部状态的围棋棋子解决方案

    实现对象的复用——享元模式(五):单纯享元模式和复合享元模式,关于享元模式的几点补充,享元模式总结

     

    代理模式-Proxy Pattern【学习难度:★★★☆☆,使用频率:★★★★☆

     

    代理模式(一):代理模式概述,代理模式结构与实现

    代理模式(二):代理模式应用实例(收费商务信息查询系统)

    代理模式(三):远程代理,虚拟代理,缓冲代理

    代理模式(四):代理模式效果与适用场景

     

     

    十一个行为型模式

     

    职责链模式-Chain of Responsibility Pattern【学习难度:★★★☆☆,使用频率:★★☆☆☆

    请求的链式处理——职责链模式(一):采购单的分级审批

    请求的链式处理——职责链模式(二):职责链模式概述

    请求的链式处理——职责链模式(三):采购单分级审批的职责链模式解决方案

    请求的链式处理——职责链模式(四):纯与不纯的职责链模式,职责链模式总结

     

    命令模式-Command Pattern【学习难度:★★★☆☆,使用频率:★★★★☆

    请求发送者与接收者解耦——命令模式(一):自定义功能键,命令模式概述

    请求发送者与接收者解耦——命令模式(二):自定义功能键的命令模式解决方案

    请求发送者与接收者解耦——命令模式(三):命令队列的实现

    请求发送者与接收者解耦——命令模式(四):撤销操作的简单实现

    请求发送者与接收者解耦——命令模式(五):请求日志

    请求发送者与接收者解耦——命令模式(六):宏命令,命令模式总结

     

    解释器模式-Interpreter Pattern【学习难度:★★★★★,使用频率:★☆☆☆☆

    自定义语言的实现——解释器模式(一):机器人控制程序

    自定义语言的实现——解释器模式(二):文法规则和抽象语法树

    自定义语言的实现——解释器模式(三):解释器模式概述

    自定义语言的实现——解释器模式(四):机器人控制程序的解释器模式解决方案

    自定义语言的实现——解释器模式(五):再谈Context的作用

    自定义语言的实现——解释器模式(六):解释器模式总结

     

    迭代器模式-Iterator Pattern【学习难度:★★★☆☆,使用频率:★★★★★

    遍历聚合对象中的元素——迭代器模式(一):销售管理系统中数据的遍历

    遍历聚合对象中的元素——迭代器模式(二):迭代器模式概述

    遍历聚合对象中的元素——迭代器模式(三):销售管理系统中数据的遍历的迭代器模式解决方案

    遍历聚合对象中的元素——迭代器模式(四):使用内部类实现迭代器

    遍历聚合对象中的元素——迭代器模式(五):JDK内置迭代器的使用

    遍历聚合对象中的元素——迭代器模式(六):迭代器模式总结

     

    中介者模式-Mediator Pattern【学习难度:★★★☆☆,使用频率:★★☆☆☆

    协调多个对象之间的交互——中介者模式(一):客户信息管理窗口的初始设计

    协调多个对象之间的交互——中介者模式(二):中介者模式概述

    协调多个对象之间的交互——中介者模式(三):客户信息管理窗口的中介者模式解决方案

    协调多个对象之间的交互——中介者模式(四):中介者与同事类的扩展

    协调多个对象之间的交互——中介者模式(五):中介者模式总结

     

    备忘录模式-Memento Pattern【学习难度:★★☆☆☆,使用频率:★★☆☆☆

    撤销功能的实现——备忘录模式(一):可悔棋的中国象棋

    撤销功能的实现——备忘录模式(二):备忘录模式概述

    撤销功能的实现——备忘录模式(三):中国象棋的备忘录模式解决方案

    撤销功能的实现——备忘录模式(四):实现多次撤销

    撤销功能的实现——备忘录模式(五):再谈备忘录的封装,备忘录模式总结

     

    观察者模式-Observer Pattern【学习难度:★★★☆☆,使用频率:★★★★★

    对象间的联动——观察者模式(一):多人联机对战游戏的设计

    对象间的联动——观察者模式(二):观察者模式概述

    对象间的联动——观察者模式(三):多人联机对战游戏的观察者模式解决方案

    对象间的联动——观察者模式(四):JDK对观察者模式的支持

    对象间的联动——观察者模式(五):观察者模式与Java事件处理

    对象间的联动——观察者模式(六):观察者模式与MVC,观察者模式总结

     

    状态模式-State Pattern【学习难度:★★★☆☆,使用频率:★★★☆☆

    处理对象的多种状态及其相互转换——状态模式(一):银行系统中的账户类设计

    处理对象的多种状态及其相互转换——状态模式(二):状态模式概述

    处理对象的多种状态及其相互转换——状态模式(三):账户类的状态模式解决方案

    处理对象的多种状态及其相互转换——状态模式(四):共享状态的实现

    处理对象的多种状态及其相互转换——状态模式(五):使用环境类实现状态转换

    处理对象的多种状态及其相互转换——状态模式(六):状态模式总结

     

    策略模式-Strategy Pattern【学习难度:★☆☆☆☆,使用频率:★★★★☆

    算法的封装与切换——策略模式(一):电影票打折方案

    算法的封装与切换——策略模式(二):策略模式概述

    算法的封装与切换——策略模式(三):电影票打折方案的策略模式解决方案

    算法的封装与切换——策略模式(四):策略模式的两个典型应用,策略模式总结

     

    模板方法模式-Template Method Pattern【学习难度:★★☆☆☆,使用频率:★★★☆☆

    模板方法模式深度解析(一):模板方法模式概述,模板方法模式结构与实现

    模板方法模式深度解析(二):模板方法模式应用实例(银行利息计算模块)

    模板方法模式深度解析(三):钩子方法的使用,模板方法模式效果与适用场景

     

    访问者模式-Visitor Pattern【学习难度:★★★★☆,使用频率:★☆☆☆☆

    操作复杂对象结构——访问者模式(一):OA系统中员工数据汇总

    操作复杂对象结构——访问者模式(二):访问者模式概述

    操作复杂对象结构——访问者模式(三):OA系统中员工数据汇总的访问者模式解决方案

    操作复杂对象结构——访问者模式(四):访问者模式与组合模式联用,访问者模式总结

     

    设计模式趣味学习(复习)

     

    设计模式与足球(一):创建型模式

    设计模式与足球(二):结构型模式

    设计模式与足球(三):行为型模式(上)

    设计模式与足球(四):行为型模式(下)

     

     

    设计模式综合应用实例

     

    多人联机射击游戏

     

    多人联机射击游戏中的设计模式应用(一):抽象工厂模式,建造者模式,工厂方法模式,迭代器模式,命令模式

    多人联机射击游戏中的设计模式应用(二):观察者模式,单例模式,状态模式,适配器模式

     

     

     

    数据库同步系统

     

    设计模式综合实例分析之数据库同步系统(一):数据库同步系统概述,建造者模式,简单工厂模式

    设计模式综合实例分析之数据库同步系统(二):享元模式,单例模式,观察者模式,模板方法模式

    设计模式综合实例分析之数据库同步系统(三):策略模式,组合模式,命令模式,职责链模式

     

     

     

    友情提示:请尊重作者劳动成果,如需转载本博客文章请注明出处!谢谢合作!

     

    【作者:刘伟  http://blog.csdn.net/lovelion

    展开全文
  • 设计模式

    千次阅读 2019-07-22 09:33:22
    设计模式简介 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过...

    设计模式简介

    设计模式(Design Patterns)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

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

    什么是 GOF?(四人帮,全拼 Gang of Four)?

    在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。

    四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。

    • 对接口编程而不是对实现编程。
    • 优先使用对象组合而不是继承。

    设计模式的使用

    设计模式在软件开发中的两个主要用途。

    开发人员的共同平台

    设计模式提供了一个标准的术语系统,且具体到特定的情景。例如,单例设计模式意味着使用单个对象,这样所有熟悉单例设计模式的开发人员都能使用单个对象,并且可以通过这种方式告诉对方,程序使用的是单例模式。

    最佳的实践

    设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。

    设计模式的类型

    根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。当然,我们还会讨论另一类设计模式:J2EE 设计模式。

    GitHub源码链接

    序号 模式 & 描述 包括
    1 创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)
    2 结构型模式 这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern)
    3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern)
    4 J2EE 模式 这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。 MVC 模式(MVC Pattern) 业务代表模式(Business Delegate Pattern) 组合实体模式(Composite Entity Pattern) 数据访问对象模式(Data Access Object Pattern) 前端控制器模式(Front Controller Pattern) 拦截过滤器模式(Intercepting Filter Pattern) 服务定位器模式(Service Locator Pattern) 传输对象模式(Transfer Object Pattern)

    下面用一个图片来整体描述一下设计模式之间的关系:

    设计模式之间的关系

    设计模式的六大原则

    1、开闭原则(Open Close Principle)

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

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

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

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

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

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

    这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

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

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

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

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

    创建型模式

    抽象工厂模式

    单例模式

    工厂模式

    建造者模式

    原型模式

    结构型模式

    代理模式

    过滤器模式

    桥接模式

    适配器模式

    外观模式

    享元模式

    装饰器模式

    组合模式

    行为型模式

    备忘录模式

    策略模式

    迭代器模式

    访问者模式

    观察者模式

    解释器模式

    空对象模式

    命令模式

    模板模式

    责任链模式

    中介者模式

    状态模式

    J2EE模式

    MVC模式

    传输对象模式

    服务定位器模式

    拦截过滤器模式

    前端控制器模式

    数据访问对象模式

    业务代表模式

    组合实体模式

    展开全文
  • 23种设计模式汇总整理

    万次阅读 多人点赞 2015-04-09 10:57:11
    设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式 结构型模式,共七种:适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 ...
  • C++ 设计模式

    万次阅读 多人点赞 2018-02-09 09:26:25
    设计模式代表了最佳的实践,在面向对象的编程中被很多老鸟们反复使用。使用设计模式有很多好处:可重用代码、保证代码可靠性、使代码更易被他人理解 ......
  • 设计模式——设计模式概述

    千次阅读 多人点赞 2019-10-12 08:07:49
    软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式主要是为了解决某类重复出现的问题而出现的一套成功或有效的解决方案。设计模式提供...
  • 设计模式(二):几种工厂模式详解

    万次阅读 2020-05-10 21:07:43
    概念 ​ 工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据...在《设计模式》一书中工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Fact
  • 设计模式看了又忘,忘了又看?

    万次阅读 多人点赞 2019-05-27 22:45:28
    设计模式收藏这篇就够了
  • 大话设计模式(一)简单工厂模式

    万次阅读 2015-04-12 16:35:37
    今天主要设计简单工厂模式即静态工厂设计模式与工厂模式即抽象模式。 其中,简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建 其他类的实例,被创建的实例通常都具有共同的...
  • 设计模式之——单例模式

    万次阅读 2021-01-28 20:40:49
    设计模式: 前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定。而是一套用来提高代码可复用性、可维护性、可读性、稳健性、以及安全性的解决方案 设计模式的本质是面向对象设计原则的实际...
  • 常用设计模式-适配器模式

    万次阅读 2020-11-27 13:15:05
    这种类型的设计模式属于结构型模式。 优点:1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。 缺点:1、过多地使用适配器,会让系统非常零乱,不易整体进行把握...
  • 大话设计模式(四)单例模式

    万次阅读 2016-09-02 10:04:47
    大话设计模式(四)单例模式的优与劣前言 首先来明确一个问题,那就是在某些情况下,有些对象,我们只需要一个就可以了,比如,一台计算机上可以连好几个打印机,但是这个计算机上的打印程序只能有一个,这里就可以...
  • 大话设计模式(五)观察者模式

    万次阅读 2016-09-05 17:38:20
    大话设计模式(五)观察者模式概念 在阎宏博士的《JAVA与模式》一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-...
  • 大话设计模式(六)工厂方法模式

    万次阅读 2016-10-09 11:23:17
    大话设计模式(六)工厂方法模式前言  今天主要讲解工厂方法模式。工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。工厂方法模式是简单工厂模式的进一步抽象和...
  • 设计模式总结

    万次阅读 2020-02-24 14:32:01
    总结所有设计模式

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 460,510
精华内容 184,204
关键字:

设计模式