JAVA设计模式

1、什么是设计模式                                                                                                                 

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

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

  • 场景:项目所在的环境
  • 问题:约束条件,项目目标等
  • 解决方案:通用、可复用的设计,解决约束达到目标。

2、设计模式的分类

 整体来讲设计模式分为三大类:编程

  • 建立型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
  • 其实还有两类:并发型模式和线程池模式。

用一个图片来总体描述一下:设计模式

3、设计模式的六大原则

  • 总原则:开闭原则(Open Close Principle)
    • 开闭原则就是说对扩展开放,对修改关闭。在程序须要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。因此一句话归纳就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,咱们须要使用接口和抽象类等,后面的具体设计中咱们会提到这点。
  • 单一责任原则
    • 不要存在多于一个致使类变动的缘由,也就是说每一个类应该实现单一的职责,如若否则,就应该把类拆分。
  • 里氏替换原则(Liskov Substitution Principle)
    • 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类能够出现的地方,子类必定能够出现。 LSP是继承复用的基石,只有当衍生类能够替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也可以在基类的基础上增长新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,因此里氏代换原则是对实现抽象化的具体步骤的规范。
    • 历史替换原则中,子类对父类的方法尽可能不要重写和重载。由于父类表明了定义好的结构,经过这个规范的接口与外界交互,子类不该该随便破坏它
  • 依赖倒转原则(Dependence Inversion Principle)
    • 这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
  • 接口隔离原则(Interface Segregation Principle)
    • 每一个接口中不存在子类用不到却必须实现的方法,若是否则,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
  • 迪米特法则(最少知道原则)(Demeter Principle)
    • 一个类对本身依赖的类知道的越少越好。也就是说不管被依赖的类多么复杂,都应该将逻辑封装在方法的内部,经过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
    • 最少知道原则的另外一个表达方式是:只与直接的朋友通讯。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。咱们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。咱们要求陌生的类不要做为局部变量出如今类中。
  • 合成复用原则(Composite Reuse Principle)
    • 原则是尽可能首先使用合成/聚合的方式,而不是使用继承。

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

  • 单例模式:某个类只能有一个实例,提供一个全局的访问点。
  • 简单模式:一个工厂类根据传入的参量决定建立出那一种产品类的实例。
  • 工厂模式:定义一个建立对象的接口,让子类决定实例化那个类。
  • 抽象工厂:建立相关或依赖对象的家族,而无需明确指定具体类。
  • 抽象工厂:建立相关或依赖对象的家族,而无需明确指定具体类。
  • 建造者模式:封装一个复杂对象的构建过程,并能够按步骤构造。
  • 原型模式:经过复制现有的实例来建立新的实例。
  • 适配器模式:将一个类的方法接口转换成客户但愿的另一个接口。
  • 组合模式:将对象组合成树形结构以表示“”部分-总体“”的层次结构。
  • 装饰模式:动态的给对象添加新的功能。
  • 代理模式:为其余对象提供一个代理以便控制这个对象的访问。
  • 亨元(蝇量)模式:经过共享技术来有效的支持大量细粒度的对象。
  • 外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
  • 桥接模式:将抽象部分和它的实现部分分离,使它们均可以独立的变化。
  • 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
  • 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
  • 策略模式:定义一系列算法,把他们封装起来,而且使它们能够相互替换。
  • 状态模式:容许一个对象在其对象内部状态改变时改变它的行为。
  • 观察者模式:对象间的一对多的依赖关系。
  • 备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
  • 中介者模式:用一个中介对象来封装一系列的对象交互。
  • 命令模式:将命令请求封装为一个对象,使得能够用不一样的请求来进行参数化。
  • 访问者模式:在不改变数据结构的前提下,增长做用于一组对象元素的新功能。
  • 责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
  • 迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。

5、Java的23中设计模式

  • 单例模式 安全

    • 单例模式,它的定义就是确保某一个类只有一个实例,而且提供一个全局访问点。
    • 单例模式具有典型的3个特色:一、只有一个实例。 二、自我实例化。 三、提供全局访问点。
    • 所以当系统中只须要一个实例对象或者系统中只容许一个公共访问点,除了这个公共访问点外,不能经过其余访问点访问该实例时,可使用单例模式。
    • 单例模式的主要优势就是节约系统资源、提升了系统效率,同时也可以严格控制客户对它的访问。也许就是由于系统中只有一个实例,这样就致使了单例类的职责太重,违背了“单一职责原则”,同时也没有抽象类,因此扩展起来有必定的困难。
    • 主要角色
      • 单例类:包含一个实例且能自行建立这个实例的类。
      • 访问类:使用单例的类。
    • 其UML结构图很是简单,就只有一个类,以下图:
    • 单例模式的实现
      • 懒汉式单例
        public class LazySingleton {
            
            private static volatile LazySingleton instance = null;        //保证 instance 在全部线程中同步
            
            private LazySingleton() {}                                    //private 避免类在外部被实例化
            
            public static synchronized LazySingleton getInstance() {
                //getInstance 方法前加同步
                if(instance == null) {
                    instance = new LazySingleton();
                }
                return instance;
            }
        }
      • 饿汉式单例
        public class HungrySingleton {
            
            private static final HungrySingleton instance = new HungrySingleton();
            
            private HungrySingleton(){}
            
            public static HungrySingleton getInstance() {
                return instance;
            }
        }
  • 工厂方法模式
    • 做为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个建立对象的接口,但由子类决定要实例化的类是哪个,也就是说工厂方法模式让实例化推迟到子类。
    • 工厂方法模式很是符合“开闭原则”,当须要增长一个新的产品时,咱们只须要增长一个具体的产品类和与之对应的具体工厂便可,无须修改原有系统。
    • 同时在工厂方法模式中用户只须要知道生产产品的具体工厂便可,无须关系产品的建立过程,甚至连具体的产品类名称都不须要知道。
    • 主要角色
      • ·抽象工厂(Abstract Factory):提供了建立产品的接口,调用者经过它访问具体工厂的工厂方法 newProduct() 来建立产品。
      • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的建立。
      • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
      • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来建立,它同具体工厂之间一一对应。
    • 虽然他很好的符合了“开闭原则”,可是因为每新增一个新产品时就须要增长两个类,这样势必会致使系统的复杂度增长。其UML结构图
    • 模式的实现:
      public interface Product {
          public void  show();
      }
      
      public class ConcreteProduct1 implements Product {
      
          public void show() {
              System.out.println("具体产品1显示....");
          }
      }
      
      public class ConcreteProduct2 implements Product {
      
          public void show() {
              System.out.println("具体产品1显示....");
          }
      }
      
      public interface AbstractFactory {
          
          public Product newProduct();
      }
      
      public class ConcreteFactory1 implements AbstractFactory {
      
          public Product newProduct() {
              System.out.println("具体工厂1生成-->具体产品1...");
              return new ConcreteProduct1();
          }
      }
      
      public class ConcreteFactory2 implements AbstractFactory {
      
          public Product newProduct() {
              System.out.println("具体工厂2生成-->具体产品2...");
              return new ConcreteProduct2();
          }
      }
      
      public class AbstractFactoryTest {
          
          public static void main(String[] args) {
              try {
                  Class<?> c = Class.forName("com.lynn.learning.designPattern.factoryMethod.ConcreteFactory2");
                  AbstractFactory af = (AbstractFactory) c.newInstance();
                  Product a = af.newProduct();
                  a.show();
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
      }
  • 抽象工厂模
    • 所谓抽象工厂模式就是提供一个接口,用于建立相关或者依赖对象的家族,而不须要明确指定具体类。
    • 他容许客户端使用抽象的接口来建立一组相关的产品,而不须要关系实际产出的具体产品是什么。这样一来,客户就能够从具体的产品中被解耦。
    • 它的优势是隔离了具体类的生成,使得客户端不须要知道什么被建立了,而缺点就在于新增新的行为会比较麻烦,由于当添加一个新的产品对象时,须要更加须要更改接口及其下全部子类。
    • 主要角色:
      • 抽象工厂(Abstract Factory):提供了建立产品的接口,它包含多个建立产品的方法 newProduct(),能够建立多个不一样等级的产品。
      • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的建立。
      • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
      • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来建立,它 同具体工厂之间是多对一的关系。
    • 其UML结构图以下:
    • 模式实现:
      public interface Animal {
          public void show();
      }
      
      public class Cattle implements Animal {
      
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工厂模式测试");
          
          public Cattle() {
              Container contentPane=jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/A_Cattle.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class Horse implements Animal {
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工厂模式测试");
          
          public Horse() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/A_Horse.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public interface Farm {
          public Animal newAnimal();
          public Plant newPlant();
      }
      
      public class Fruitage implements Plant {
      
          JScrollPane sp;
          JFrame jf = new JFrame("抽象工厂模式测试");
          
          public Fruitage() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/P_Vegetables.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class Vegetables implements Plant {
      
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工厂模式测试");
          
          public Vegetables() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1, 1));
              p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/P_Vegetables.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class SGfarm implements Farm {
      
          public Animal newAnimal() {
              System.out.println("新牛出生!");
              return new Cattle();
          }
      
          public Plant newPlant() {
              System.out.println("蔬菜长成!");
              return new Vegetables();
          }
      }
      
      public class SRfarm implements Farm {
      
          public Animal newAnimal() {
              System.out.println("新马出生!");
              return new Horse();
          }
      
          public Plant newPlant() {
              System.out.println("水果长成!");
              return new Fruitage();
          }
      }
      
      public class FarmTest {
          
          public static void main(String[] args) {
              try {
                  Class<?> c = Class.forName("com.lynn.learning.designPattern.abstractFactory.SGfarm");
                  Farm f = (Farm) c.newInstance();
                  Animal a = f.newAnimal();
                  Plant p = f.newPlant();
                  a.show();
                  p.show();
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
      }
  • 建造者模式
    • 对于建造者模式而已,它主要是将一个复杂对象的构建与表示分离,使得一样的构建过程能够建立不一样的表示。适用于那些产品对象的内部结构比较复杂。
    • 建造者模式将复杂产品的构建过程封装分解在不一样的方法中,使得建立过程很是清晰,可以让咱们更加精确的控制复杂产品对象的建立过程,同时它隔离了复杂产品对象的建立和使用,使得相同的建立过程可以建立不一样的产品。
    • 可是若是某个产品的内部结构过于复杂,将会致使整个系统变得很是庞大,不利于控制,同时若几个产品之间存在较大的差别,则不适用建造者模式,毕竟这个世界上存在相同点大的两个产品并非不少,因此它的使用范围有限。
    • 优势:
      • 各个具体的建造者相互独立,有利于系统的扩展。
      • 客户端没必要知道产品内部组成的细节,便于控制细节风险
    • 缺点:
      • 产品的组成部分必须相同,这限制了其使用范围。
      • 若是产品的内部变化复杂,该模式会增长不少的建造者类。
    • 主要角色:
      • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来建立其各个滅部件。
      • 抽象建造者(Builder):它是一个包含建立产品各个子部件的抽象方法的接口,一般还包含一个返回复杂产品的方法 getResult()。
      • 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体建立方法。
      • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的建立,在指挥者中不涉及具体产品的信息。
    • 其UML结构图:
    • 模式实现:
  • 原型模式
    • 在咱们应用程序可能有某些对象的结构比较复杂,可是咱们又须要频繁的使用它们,若是这个时候咱们来不断的新建这个对象势必会大大损耗系统内存的,这个时候咱们须要使用原型模式来对这个结构复杂又要频繁使用的对象进行克隆。因此原型模式就是用原型实例指定建立对象的种类,而且经过复制这些原型建立新的对象。
    • 它主要应用与那些建立新对象的成本过大时。它的主要优势就是简化了新对象的建立过程,提升了效率,同时原型模式提供了简化的建立结构。
    • 主要角色:
      • 抽象原型类:规定了具体原型对象必须实现的接口。
      • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
      • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
    • UML结构图:
    • 模式实现:
      public interface Shape extends Cloneable {
          public Object clone();            //拷贝
          public void countArea();        //计算面积
      }
      
      public class Square implements Shape {
         
          private Scanner input;
      
          public Object clone() {
              Square b = null;
              try {
                  b = (Square)super.clone();
              } catch(CloneNotSupportedException e) {
                  System.out.println("拷贝正方形失败!");
              }
              return b;
          }
          
          public void countArea() {
              int a = 0;
              System.out.print("这是一个正方形,请输入它的边长:");
              input = new Scanner(System.in);
              a=input.nextInt();
              System.out.print("该正方形的面积=" + a * a + "\n");
          }
      }
      
      public class Circle implements Shape {
      
          private Scanner input;
      
          public Object clone() {
              Circle w = null;
              try {
                  w = (Circle)super.clone();
              } catch(CloneNotSupportedException e) {
                  System.out.println("拷贝圆失败!");
              }
              return w;
          }
          
          public void countArea() {
              int r=0;
              System.out.print("这是一个圆,请输入圆的半径:");
              input = new Scanner(System.in);
              r = input.nextInt();
              System.out.println("该圆的面积=" + 3.1415 * r * r + "\n");
          }
      
      }
      
      public class ProtoTypeManager {
          private HashMap<String, Shape> ht = new HashMap<String,Shape>(); 
          
          public ProtoTypeManager() {
              ht.put("Circle", new Circle());
              ht.put("Square", new Square());
          } 
          
          public void addshape(String key, Shape obj) {
              ht.put(key, obj);
          }
          
          public Shape getShape(String key) {
              Shape temp = ht.get(key);
              return (Shape) temp.clone();
          }
      }
      
      public class ProtoTypeShape {
          public static void main(String[] args) {
              ProtoTypeManager pm = new ProtoTypeManager();    
              Shape obj1 = (Circle)pm.getShape("Circle");
              obj1.countArea();          
              Shape obj2 = (Shape)pm.getShape("Square");
              obj2.countArea();     
          }
      }
  • 适配器模式(Adapter)
    • 在咱们的应用程序中咱们可能须要将两个不一样接口的类来进行通讯,在不修改这两个的前提下咱们可能会须要某个中间件来完成这个衔接的过程。这个中间件就是适配器。
    • 所谓适配器模式就是将一个类的接口,转换成客户指望的另外一个接口。它可让本来两个不兼容的接口可以无缝完成对接。
    • 做为中间件的适配器将目标类和适配者解耦,增长了类的透明性和可复用性。
    • 主要角色
      • 目标(Target)接口:当前系统业务所期待的接口,它能够是抽象类或接口。
      • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
      • 适配器(Adapter)类:它是一个转换器,经过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
    • 优势
      • 客户端经过适配器能够透明地调用目标接口。
      • 复用了现存的类,程序员不须要修改原有代码而重用现有的适配者类。
      • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
    • 缺点
      • 对类适配器来讲,更换适配器的实现过程比较复杂。
    • UML结构图:
    • 模式实现:
      • 类适配器模式
        public interface Target {
            public void request();
        }
        
        public class Adaptee {
            public void specificRequest() {       
                System.out.println("适配者中的业务代码被调用!");
            }
        }
        
        public class ClassAdapter extends Adaptee implements Target {
        
            public void request() {
                specificRequest();
            }
        }
        
        public class ClassAdapterTest {
            public static void main(String[] args) {
                System.out.println("类适配器模式测试:");
                Target target = new ClassAdapter();
                target.request();
            }
        }
      • 对象适配器模式
        public interface Target {
            public void request();
        }
        
        public class Adaptee {
            public void specificRequest() {       
                System.out.println("适配者中的业务代码被调用!");
            }
        }
        
        public class ObjectAdapter implements Target {
        
            private Adaptee adaptee;
            
            public ObjectAdapter(Adaptee adaptee) {
                this.adaptee = adaptee;
            }
            
            public void request() {
                adaptee.specificRequest();
            }
        }
        
        public class ObjectAdapterTest {
            public static void main(String[] args) {
                System.out.println("对象适配器模式测试:");
                Adaptee adaptee = new Adaptee();
                Target target = new ObjectAdapter(adaptee);
                target.request();
            }
        }
  • 桥接模式
    • 若是说某个系统可以从多个角度来进行分类,且每一种分类均可能会变化,那么咱们须要作的就是讲这多个角度分离出来,使得他们能独立变化,减小他们之间的耦合,这个分离过程就使用了桥接模式。
    • 所谓桥接模式就是讲抽象部分和实现部分隔离开来,使得他们可以独立变化。桥接模式将继承关系转化成关联关系,封装了变化,完成了解耦,减小了系统中类的数量,也减小了代码量。
    • 优势
      • 因为抽象与实现分离,因此扩展能力强;
      • 其实现细节对客户透明。
    • 缺点
      • 因为聚合关系创建在抽象层,要求开发者针对抽象化进行设计与编程,这增长了系统的理解与设计难度。
    • 主要角色UML结构图:
      • 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
      • 扩展抽象化(Refined    Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并经过组合关系调用实现化角色中的业务方法。
      • 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
      • 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
    • 模式实现:
      public interface Implementor { public void OperationImpl(); } public class ConcreteImplementorA implements Implementor { public void OperationImpl() { System.out.println("具体实现化(Concrete Implementor)角色被访问" ); } } public abstract class Abstraction { protected Implementor imple; protected Abstraction(Implementor imple) { this.imple = imple; } public abstract void Operation(); } public class RefinedAbstraction extends Abstraction{ protected RefinedAbstraction(Implementor imple) { super(imple); } public void Operation() { System.out.println("扩展抽象化(Refined Abstraction)角色被访问" ); imple.OperationImpl(); } } public class BridgeTest { public static void main(String[] args) { Implementor imple = new ConcreteImplementorA(); Abstraction abs = new RefinedAbstraction(imple); abs.Operation(); } }
  • 组合模式装饰模式
    • 组合模式组合多个对象造成树形结构以表示“总体-部分”的结构层次。
    • 它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程当中无须进行区分,能够对他们进行一致的处理。
    • 在使用组合模式中须要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式可以将叶子节点和对象节点进行一致处理的缘由。
    • 虽然组合模式可以清晰地定义分层次的复杂对象,也使得增长新构件也更容易,可是这样就致使了系统的设计变得更加抽象,若是系统的业务规则比较复杂的话,使用组合模式就有必定的挑战了。
    • 优势
      • 组合模式使得客户端代码能够一致地处理单个对象和组合对象,无须关心本身处理的是单个对象,仍是组合对象,这简化了客户端代码;
      • 更容易在组合体内加入新的对象,客户端不会由于加入了新的对象而更改源代码,知足“开闭原则”;
    • 缺点
      • 设计较复杂,客户端须要花更多时间理清类之间的层次关系;
      • 不容易限制容器中的构件;
      • 不容易用继承的方法来增长构件的新功能;
    • 主要角色
      • 抽象构件(Component)角色:它的主要做用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工做由树枝构件完成。
      • 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
      • 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要做用是存储和管理子部件,一般包含 Add()、Remove()、GetChild() 等方法。
    • UML结构图:
    • 模式实现
      public interface Component {
          public void add(Component c);
          public void remove(Component c);
          public Component getChild(int i);
          public void operation();
      }
      
      public class Leaf implements Component {
          
          private String name;
          
          public Leaf(String name) {
              this.name = name;
          }
      
          public void add(Component c) {
              
          }
      
          public void remove(Component c) {
          }
      
          public Component getChild(int i) {
              return null;
          }
      
          public void operation() {
              System.out.println("树叶" + name + ":被访问!"); 
          }
      }
      
      public class Composite implements Component {
          
          private ArrayList<Component> children = new ArrayList<Component>();
      
          public void add(Component c) {
              children.add(c);
          }
      
          public void remove(Component c) {
              children.remove(c);
          }
      
          public Component getChild(int i) {
              return children.get(i);
          }
      
          public void operation() {
              for(Object obj : children) {
                  ((Component)obj).operation();
              }
          }
      }
      
      public class CompositePattern {
          public static void main(String[] args) {
              Component c0 = new Composite();
              Component c1 = new Composite();
              Component leaf1 = new Leaf("1");
              Component leaf2 = new Leaf("2");
              Component leaf3 = new Leaf("3");
              c0.add(leaf1);
              c0.add(c1);
              c1.add(leaf2);
              c1.add(leaf3);
              c0.operation();
          }
      }
  • 装饰模式
    • 咱们能够经过继承和组合的方式来给一个对象添加行为,虽然使用继承可以很好拥有父类的行为,可是它存在几个缺陷:1、对象之间的关系复杂的话,系统变得复杂不利于维护。2、容易产生“类爆炸”现象。3、是静态的。在这里咱们能够经过使用装饰者模式来解决这个问题。
    • 装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。虽然装饰者模式可以动态将责任附加到对象上,可是他会产生许多的细小对象,增长了系统的复杂度。
    • 优势
      • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
      • 能够设计出多个不一样的具体装饰类,创造出多个不一样行为的组合。
    • 缺点
      • 装饰模式增长了许多子类,若是过分使用会使程序变得很复杂。
    • 主要角色
      • 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
      • 具体构件(Concrete    Component)角色:实现抽象构件,经过装饰角色为其添加一些职责。
      • 抽象装饰(Decorator)角色:实现抽象构件,并包含具体构件的实例,能够经过其子类扩展具体构件的功能。
      • 体装饰(ConcreteDecorator)角色:继承抽象装饰的相关方法,并给具体构件对象添加附加的责任。
    • UML结构图:
    • 模式实现
      public interface Component {
          public void operation();
      }
      
      public class ConcreteComponent implements Component{
          
          public ConcreteComponent() {
              System.out.println("建立具体构件角色");
          }
      
          public void operation() {
              System.out.println("调用具体构件角色的方法operation()");
          }
      }
      
      public class Decorator implements Component {
      
          private Component component;   
          
          public Decorator(Component component) {
              this.component = component;
          }   
          
          public void operation() {
              component.operation();
          }
      }
      
      public class ConcreteDecorator extends Decorator {
          
          public ConcreteDecorator(Component component) {
              super(component);
          }
          
          public void operation() {
              super.operation();
              addedFunction();
          }
          
          public void addedFunction() {
              System.out.println("为具体构件角色增长额外的功能addedFunction()");           
          }
      }
      
      public class DecoratorPattern {
          public static void main(String[] args) {
              Component p = new ConcreteComponent();
              p.operation();
              System.out.println("---------------------------------");
              Component d = new ConcreteDecorator(p);
              d.operation();
          }
      }
  • 代理模式
  • 亨元模式
  • 外观模式
相关文章
相关标签/搜索