JAVA设计模式
一、什么是设计模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:
模式:在某些场景下,针对某类问题的某种通用的解决方案。
- 场景:项目所在的环境
- 问题:约束条件,项目目标等
- 解决方案:通用、可复用的设计,解决约束达到目标。
二、设计模式的分类
总体来说设计模式分为三大类:
- 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
- 其实还有两类:并发型模式和线程池模式。
用一个图片来整体描述一下:

三、设计模式的六大原则
- 总原则:开闭原则(Open Close Principle)
- 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。
- 单一责任原则
- 不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。
- 里氏替换原则(Liskov Substitution Principle)
- 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
- 历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它
- 依赖倒转原则(Dependence Inversion Principle)
- 这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
- 接口隔离原则(Interface Segregation Principle)
- 每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
- 迪米特法则(最少知道原则)(Demeter Principle)
- 一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
- 最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
- 合成复用原则(Composite Reuse Principle)
- 原则是尽量首先使用合成/聚合的方式,而不是使用继承。
四、各分类中模式的关键点
- 单例模式:某个类只能有一个实例,提供一个全局的访问点。
- 简单模式:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
- 工厂模式:定义一个创建对象的接口,让子类决定实例化那个类。
- 抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
- 抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
- 建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
- 原型模式:通过复制现有的实例来创建新的实例。
- 适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
- 组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
- 装饰模式:动态的给对象添加新的功能。
- 代理模式:为其他对象提供一个代理以便控制这个对象的访问。
- 亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
- 外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
- 桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
- 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
- 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
- 策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
- 状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
- 观察者模式:对象间的一对多的依赖关系。
- 备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
- 中介者模式:用一个中介对象来封装一系列的对象交互。
- 命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
- 访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
- 责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
- 迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
五、Java的23中设计模式
-
单例模式
- 单例模式,它的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。
- 单例模式具备典型的3个特点:1、只有一个实例。 2、自我实例化。 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(); } }
- 装饰模式
- 我们可以通过继承和组合的方式来给一个对象添加行为,虽然使用继承能够很好拥有父类的行为,但是它存在几个缺陷:一、对象之间的关系复杂的话,系统变得复杂不利于维护。二、容易产生“类爆炸”现象。三、是静态的。在这里我们可以通过使用装饰者模式来解决这个问题。
- 装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。虽然装饰者模式能够动态将责任附加到对象上,但是他会产生许多的细小对象,增加了系统的复杂度。
- 优点
- 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
- 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。
- 缺点
- 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。
- 主要角色
- 抽象构件(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(); } }
- 代理模式
- 亨元模式
- 外观模式











浙公网安备 33010602011771号