- 设计模式教程
- 设计模式 - 首页
- 设计模式 - 概述
- 设计模式 - 工厂模式
- 抽象工厂模式
- 设计模式 - 单例模式
- 设计模式 - 建造者模式
- 设计模式 - 原型模式
- 设计模式 - 适配器模式
- 设计模式 - 桥接模式
- 设计模式 - 过滤器模式
- 设计模式 - 组合模式
- 设计模式 - 装饰器模式
- 设计模式 - 外观模式
- 设计模式 - 享元模式
- 设计模式 - 代理模式
- 责任链模式
- 设计模式 - 命令模式
- 设计模式 - 解释器模式
- 设计模式 - 迭代器模式
- 设计模式 - 中介者模式
- 设计模式 - 备忘录模式
- 设计模式 - 观察者模式
- 设计模式 - 状态模式
- 设计模式 - 空对象模式
- 设计模式 - 策略模式
- 设计模式 - 模板模式
- 设计模式 - 访问者模式
- 设计模式 - MVC 模式
- 业务代表模式
- 组合实体模式
- 数据访问对象模式
- 前端控制器模式
- 拦截过滤器模式
- 服务定位器模式
- 传输对象模式
- 设计模式资源
- 设计模式 - 问答
- 设计模式 - 速查
- 设计模式 - 有用资源
- 设计模式 - 讨论
设计模式速查
设计模式代表了经验丰富的面向对象软件开发人员使用的最佳实践。设计模式是对软件开发人员在软件开发过程中遇到的常见问题的解决方案。这些解决方案是众多软件开发人员在相当长的一段时间内通过反复试验获得的。
什么是四人帮 (GOF)?
1994年,四位作者 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 出版了一本书,名为设计模式 - 可复用面向对象软件的基础,该书开启了软件开发中设计模式的概念。
这些作者统称为四人帮 (GOF)。根据这些作者的说法,设计模式主要基于以下面向对象设计的原则。
面向接口编程,而非面向实现
优先使用对象组合而非类继承
设计模式的用法
设计模式在软件开发中主要有两个用途。
为开发人员提供一个共同的平台
设计模式提供标准术语,并针对特定场景。例如,单例设计模式表示使用单个对象,因此所有熟悉单例设计模式的开发人员都将使用单个对象,他们可以互相告知程序遵循单例模式。
最佳实践
设计模式经过长时间的演变,它们为软件开发过程中遇到的某些问题提供了最佳解决方案。学习这些模式可以帮助没有经验的开发人员轻松快速地学习软件设计。
设计模式的类型
根据设计模式参考书设计模式 - 可复用面向对象软件的基础,共有23种设计模式。这些模式可以分为三类:创建型、结构型和行为型模式。我们还将讨论另一类设计模式:J2EE 设计模式。
序号 | 模式及描述 |
---|---|
1 | 创建型模式 这些设计模式提供了一种创建对象的方式,同时隐藏了创建逻辑,而不是直接使用 new 运算符实例化对象。这使程序在决定为给定用例需要创建哪些对象时具有更大的灵活性。 |
2 | 结构型模式 这些设计模式关注类和对象的组合。继承的概念用于组合接口并定义组合对象以获得新功能的方法。 |
3 | 行为型模式 这些设计模式专门关注对象之间的通信。 |
4 | J2EE 模式 这些设计模式专门关注表示层。这些模式由 Sun Java 中心确定。 |
工厂模式
工厂模式是 Java 中最常用的设计模式之一。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方法。
在工厂模式中,我们创建对象而不向客户端公开创建逻辑,并使用公共接口引用新创建的对象。
实现
我们将创建一个Shape接口和实现Shape接口的具体类。接下来定义一个工厂类ShapeFactory。
我们的演示类FactoryPatternDemo将使用ShapeFactory来获取Shape对象。它将信息(CIRCLE / RECTANGLE / SQUARE)传递给ShapeFactory以获取其所需的 对象类型。
步骤 1
创建一个接口。
Shape.java
public interface Shape { void draw(); }
步骤 2
创建实现同一接口的具体类。
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
步骤 3
创建一个工厂,根据给定的信息生成具体类的对象。
ShapeFactory.java
public class ShapeFactory { //use getShape method to get object of type shape public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
步骤 4
使用工厂通过传递信息(例如类型)来获取具体类的对象。
FactoryPatternDemo.java
public class FactoryPatternDemo { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); //get an object of Circle and call its draw method. Shape shape1 = shapeFactory.getShape("CIRCLE"); //call draw method of Circle shape1.draw(); //get an object of Rectangle and call its draw method. Shape shape2 = shapeFactory.getShape("RECTANGLE"); //call draw method of Rectangle shape2.draw(); //get an object of Square and call its draw method. Shape shape3 = shapeFactory.getShape("SQUARE"); //call draw method of square shape3.draw(); } }
步骤 5
验证输出。
Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.
设计模式 - 抽象工厂模式
抽象工厂模式围绕一个超级工厂工作,该超级工厂创建其他工厂。这个工厂也称为工厂的工厂。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方法。
在抽象工厂模式中,一个接口负责创建相关对象的工厂,而无需明确指定它们的类。每个生成的工厂都可以根据工厂模式提供对象。
实现
我们将创建一个 Shape 接口和一个实现它的具体类。下一步,我们创建一个抽象工厂类 AbstractFactory。定义工厂类 ShapeFactory,它扩展 AbstractFactory。创建工厂创建者/生成器类 FactoryProducer。
我们的演示类 AbstractFactoryPatternDemo 使用 FactoryProducer 获取 AbstractFactory 对象。它将信息(CIRCLE / RECTANGLE / SQUARE 用于 Shape)传递给 AbstractFactory 以获取其所需的 对象类型。
步骤 1
为形状创建接口。
Shape.java
public interface Shape { void draw(); }
步骤 2
创建实现同一接口的具体类。
RoundedRectangle.java
public class RoundedRectangle implements Shape { @Override public void draw() { System.out.println("Inside RoundedRectangle::draw() method."); } }
RoundedSquare.java
public class RoundedSquare implements Shape { @Override public void draw() { System.out.println("Inside RoundedSquare::draw() method."); } }
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
步骤 3
创建一个抽象类以获取普通形状对象和圆角形状对象的工厂。
AbstractFactory.java
public abstract class AbstractFactory { abstract Shape getShape(String shapeType) ; }
步骤 4
创建扩展 AbstractFactory 的工厂类,以根据给定的信息生成具体类的对象。
ShapeFactory.java
public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); }else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
RoundedShapeFactory.java
public class RoundedShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new RoundedRectangle(); }else if(shapeType.equalsIgnoreCase("SQUARE")){ return new RoundedSquare(); } return null; } }
步骤 5
创建一个工厂生成器/生产者类,通过传递信息(如 Shape)来获取工厂。
FactoryProducer.java
public class FactoryProducer { public static AbstractFactory getFactory(boolean rounded){ if(rounded){ return new RoundedShapeFactory(); }else{ return new ShapeFactory(); } } }
步骤 6
使用 FactoryProducer 获取 AbstractFactory,以便通过传递信息(如类型)来获取具体类的工厂。
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo { public static void main(String[] args) { //get shape factory AbstractFactory shapeFactory = FactoryProducer.getFactory(false); //get an object of Shape Rectangle Shape shape1 = shapeFactory.getShape("RECTANGLE"); //call draw method of Shape Rectangle shape1.draw(); //get an object of Shape Square Shape shape2 = shapeFactory.getShape("SQUARE"); //call draw method of Shape Square shape2.draw(); //get shape factory AbstractFactory shapeFactory1 = FactoryProducer.getFactory(true); //get an object of Shape Rectangle Shape shape3 = shapeFactory1.getShape("RECTANGLE"); //call draw method of Shape Rectangle shape3.draw(); //get an object of Shape Square Shape shape4 = shapeFactory1.getShape("SQUARE"); //call draw method of Shape Square shape4.draw(); } }
步骤 7
验证输出。
Inside Rectangle::draw() method. Inside Square::draw() method. Inside RoundedRectangle::draw() method. Inside RoundedSquare::draw() method.
单例模式
单例模式是 Java 中最简单的设计模式之一。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方法。
此模式涉及单个类,该类负责创建自己的对象,同时确保只创建单个对象。此类提供了一种访问其唯一对象的方式,可以直接访问而无需实例化类的对象。
实现
我们将创建一个SingleObject类。SingleObject类的构造函数是私有的,并且具有自身的静态实例。
SingleObject类提供了一种静态方法,用于将静态实例提供给外部世界。我们的演示类SingletonPatternDemo将使用SingleObject类来获取SingleObject对象。
步骤 1
创建一个单例类。
SingleObject.java
public class SingleObject { //create an object of SingleObject private static SingleObject instance = new SingleObject(); //make the constructor private so that this class cannot be //instantiated private SingleObject(){} //Get the only object available public static SingleObject getInstance(){ return instance; } public void showMessage(){ System.out.println("Hello World!"); } }
步骤 2
从单例类获取唯一对象。
SingletonPatternDemo.java
public class SingletonPatternDemo { public static void main(String[] args) { //illegal construct //Compile Time Error: The constructor SingleObject() is not visible //SingleObject object = new SingleObject(); //Get the only object available SingleObject object = SingleObject.getInstance(); //show the message object.showMessage(); } }
步骤 3
验证输出。
Hello World!
建造者模式
建造者模式使用简单的对象和逐步的方法构建复杂的对象。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方法。
建造者类逐步构建最终对象。此建造者独立于其他对象。
实现
我们考虑了快餐店的业务案例,其中典型的餐点可能是汉堡和冷饮。汉堡可以是素食汉堡或鸡肉汉堡,并用包装纸包装。冷饮可以是可乐或百事可乐,并装在瓶子里。
我们将创建一个Item接口,表示汉堡和冷饮等食物,以及实现Item接口的具体类,以及一个Packing接口,表示食物的包装,以及实现Packing接口的具体类,例如汉堡将用包装纸包装,冷饮将装在瓶子里。
然后,我们创建一个Meal类,其中包含Item的ArrayList,以及一个MealBuilder,用于通过组合Item来构建不同类型的Meal对象。我们的演示类BuilderPatternDemo将使用MealBuilder来构建一个Meal。
步骤 1
创建一个表示食物和包装的接口 Item。
Item.java
public interface Item { public String name(); public Packing packing(); public float price(); }
Packing.java
public interface Packing { public String pack(); }
步骤 2
创建实现 Packing 接口的具体类。
Wrapper.java
public class Wrapper implements Packing { @Override public String pack() { return "Wrapper"; } }
Bottle.java
public class Bottle implements Packing { @Override public String pack() { return "Bottle"; } }
步骤 3
创建实现 Item 接口的抽象类,提供默认功能。
Burger.java
public abstract class Burger implements Item { @Override public Packing packing() { return new Wrapper(); } @Override public abstract float price(); }
ColdDrink.java
public abstract class ColdDrink implements Item { @Override public Packing packing() { return new Bottle(); } @Override public abstract float price(); }
步骤 4
创建扩展 Burger 和 ColdDrink 类的具体类
VegBurger.java
public class VegBurger extends Burger { @Override public float price() { return 25.0f; } @Override public String name() { return "Veg Burger"; } }
ChickenBurger.java
public class ChickenBurger extends Burger { @Override public float price() { return 50.5f; } @Override public String name() { return "Chicken Burger"; } }
Coke.java
public class Coke extends ColdDrink { @Override public float price() { return 30.0f; } @Override public String name() { return "Coke"; } }
Pepsi.java
public class Pepsi extends ColdDrink { @Override public float price() { return 35.0f; } @Override public String name() { return "Pepsi"; } }
步骤 5
创建一个 Meal 类,其中定义了上述 Item 对象。
Meal.java
import java.util.ArrayList; import java.util.List; public class Meal { private List<Item> items = new ArrayList<Item>(); public void addItem(Item item){ items.add(item); } public float getCost(){ float cost = 0.0f; for (Item item : items) { cost += item.price(); } return cost; } public void showItems(){ for (Item item : items) { System.out.print("Item : "+item.name()); System.out.print(", Packing : "+item.packing().pack()); System.out.println(", Price : "+item.price()); } } }
步骤 6
创建一个 MealBuilder 类,这是负责创建 Meal 对象的实际建造者类。
MealBuilder.java
public class MealBuilder { public Meal prepareVegMeal (){ Meal meal = new Meal(); meal.addItem(new VegBurger()); meal.addItem(new Coke()); return meal; } public Meal prepareNonVegMeal (){ Meal meal = new Meal(); meal.addItem(new ChickenBurger()); meal.addItem(new Pepsi()); return meal; } }
步骤 7
BuiderPatternDemo 使用 MealBuider 演示建造者模式。
BuilderPatternDemo.java
public class BuilderPatternDemo { public static void main(String[] args) { MealBuilder mealBuilder = new MealBuilder(); Meal vegMeal = mealBuilder.prepareVegMeal(); System.out.println("Veg Meal"); vegMeal.showItems(); System.out.println("Total Cost: " +vegMeal.getCost()); Meal nonVegMeal = mealBuilder.prepareNonVegMeal(); System.out.println("\n\nNon-Veg Meal"); nonVegMeal.showItems(); System.out.println("Total Cost: " +nonVegMeal.getCost()); } }
步骤 8
验证输出。
Veg Meal Item : Veg Burger, Packing : Wrapper, Price : 25.0 Item : Coke, Packing : Bottle, Price : 30.0 Total Cost: 55.0 Non-Veg Meal Item : Chicken Burger, Packing : Wrapper, Price : 50.5 Item : Pepsi, Packing : Bottle, Price : 35.0 Total Cost: 85.5
原型模式
原型模式指的是在考虑性能的情况下创建重复对象。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方法。
此模式涉及实现一个原型接口,该接口指示创建当前对象的克隆。当直接创建对象成本很高时,可以使用此模式。例如,对象需要在代价高昂的数据库操作之后创建。我们可以缓存对象,在下次请求时返回其克隆,并在需要时更新数据库,从而减少数据库调用次数。
实现
我们将创建一个抽象类Shape和扩展Shape类的具体类。下一步定义一个ShapeCache类,它将形状对象存储在Hashtable中,并在请求时返回它们的克隆。
我们的演示类PrototypPatternDemo将使用ShapeCache类获取Shape对象。
步骤 1
创建一个实现Clonable接口的抽象类。
Shape.java
public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }
步骤 2
创建扩展上述类的具体类。
Rectangle.java
public class Rectangle extends Shape { public Rectangle(){ type = "Rectangle"; } @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
Square.java
public class Square extends Shape { public Square(){ type = "Square"; } @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
Circle.java
public class Circle extends Shape { public Circle(){ type = "Circle"; } @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
步骤 3
创建一个类,从数据库获取具体类并将它们存储在Hashtable中。
ShapeCache.java
import java.util.Hashtable; public class ShapeCache { private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } // for each shape run database query and create shape // shapeMap.put(shapeKey, shape); // for example, we are adding three shapes public static void loadCache() { Circle circle = new Circle(); circle.setId("1"); shapeMap.put(circle.getId(),circle); Square square = new Square(); square.setId("2"); shapeMap.put(square.getId(),square); Rectangle rectangle = new Rectangle(); rectangle.setId("3"); shapeMap.put(rectangle.getId(),rectangle); } }
步骤 4
PrototypePatternDemo使用ShapeCache类获取存储在Hashtable中的形状的克隆。
PrototypePatternDemo.java
public class PrototypePatternDemo { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape = (Shape) ShapeCache.getShape("1"); System.out.println("Shape : " + clonedShape.getType()); Shape clonedShape2 = (Shape) ShapeCache.getShape("2"); System.out.println("Shape : " + clonedShape2.getType()); Shape clonedShape3 = (Shape) ShapeCache.getShape("3"); System.out.println("Shape : " + clonedShape3.getType()); } }
步骤 5
验证输出。
Shape : Circle Shape : Square Shape : Rectangle
适配器模式 (Adapter Pattern)
适配器模式作为两个不兼容接口之间的桥梁。这种设计模式属于结构型模式,因为它组合了两个独立接口的功能。
此模式涉及一个类,负责连接独立或不兼容接口的功能。一个现实生活中的例子是读卡器,它充当存储卡和笔记本电脑之间的适配器。您可以将存储卡插入读卡器,然后将读卡器插入笔记本电脑,以便通过笔记本电脑读取存储卡。
我们将通过以下示例演示适配器模式的使用,其中一个音频播放器设备只能播放mp3文件,并希望使用能够播放vlc和mp4文件的更高级的音频播放器。
实现
我们有一个接口MediaPlayer接口和一个实现MediaPlayer接口的具体类AudioPlayer。AudioPlayer默认可以播放mp3格式的音频文件。
我们还有另一个接口AdvancedMediaPlayer和实现AdvancedMediaPlayer接口的具体类。这些类可以播放vlc和mp4格式的文件。
我们希望使AudioPlayer也能播放其他格式。为此,我们创建了一个适配器类MediaAdapter,它实现了MediaPlayer接口并使用AdvancedMediaPlayer对象播放所需的格式。
AudioPlayer使用适配器类MediaAdapter,将所需的音频类型传递给它,而无需知道可以播放所需格式的实际类。我们的演示类AdapterPatternDemo将使用AudioPlayer类播放各种格式。
步骤 1
为媒体播放器和高级媒体播放器创建接口。
MediaPlayer.java
public interface MediaPlayer { public void play(String audioType, String fileName); }
AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer { public void playVlc(String fileName); public void playMp4(String fileName); }
步骤 2
创建实现AdvancedMediaPlayer接口的具体类。
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{ @Override public void playVlc(String fileName) { System.out.println("Playing vlc file. Name: "+ fileName); } @Override public void playMp4(String fileName) { //do nothing } }
Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{ @Override public void playVlc(String fileName) { //do nothing } @Override public void playMp4(String fileName) { System.out.println("Playing mp4 file. Name: "+ fileName); } }
步骤 3
创建实现MediaPlayer接口的适配器类。
MediaAdapter.java
public class MediaAdapter implements MediaPlayer { AdvancedMediaPlayer advancedMusicPlayer; public MediaAdapter(String audioType){ if(audioType.equalsIgnoreCase("vlc") ){ advancedMusicPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer = new Mp4Player(); } } @Override public void play(String audioType, String fileName) { if(audioType.equalsIgnoreCase("vlc")){ advancedMusicPlayer.playVlc(fileName); }else if(audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer.playMp4(fileName); } } }
步骤 4
创建实现MediaPlayer接口的具体类。
AudioPlayer.java
public class AudioPlayer implements MediaPlayer { MediaAdapter mediaAdapter; @Override public void play(String audioType, String fileName) { //inbuilt support to play mp3 music files if(audioType.equalsIgnoreCase("mp3")){ System.out.println("Playing mp3 file. Name: "+ fileName); } //mediaAdapter is providing support to play other file formats else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){ mediaAdapter = new MediaAdapter(audioType); mediaAdapter.play(audioType, fileName); } else{ System.out.println("Invalid media. "+ audioType + " format not supported"); } } }
步骤 5
使用AudioPlayer播放不同类型的音频格式。
AdapterPatternDemo.java
public class AdapterPatternDemo { public static void main(String[] args) { AudioPlayer audioPlayer = new AudioPlayer(); audioPlayer.play("mp3", "beyond the horizon.mp3"); audioPlayer.play("mp4", "alone.mp4"); audioPlayer.play("vlc", "far far away.vlc"); audioPlayer.play("avi", "mind me.avi"); } }
步骤 6
验证输出。
Playing mp3 file. Name: beyond the horizon.mp3 Playing mp4 file. Name: alone.mp4 Playing vlc file. Name: far far away.vlc Invalid media. avi format not supported
桥接模式 (Bridge Pattern)
桥接模式用于我们需要将抽象与其实现解耦的情况,以便两者可以独立变化。这种设计模式属于结构型模式,因为它通过提供一个桥接结构来解耦实现类和抽象类。
此模式涉及一个充当桥梁的接口,它使具体类的功能独立于接口实现类。两种类型的类可以在结构上进行更改,而不会相互影响。
我们将通过以下示例演示桥接模式的使用,其中可以使用相同的抽象类方法但在不同的桥接实现类中绘制不同颜色的圆。
实现
我们有一个接口DrawAPI接口,它充当桥接实现器,以及实现DrawAPI接口的具体类RedCircle、GreenCircle。Shape是一个抽象类,并将使用DrawAPI的对象。我们的演示类BridgePatternDemo将使用Shape类绘制不同颜色的圆。
步骤 1
创建桥接实现器接口。
DrawAPI.java
public interface DrawAPI { public void drawCircle(int radius, int x, int y); }
步骤 2
创建实现DrawAPI接口的具体桥接实现类。
RedCircle.java
public class RedCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: red, radius: " + radius +", x: " +x+", "+ y +"]"); } }
GreenCircle.java
public class GreenCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: green, radius: " + radius +", x: " +x+", "+ y +"]"); } }
步骤 3
使用DrawAPI接口创建一个抽象类Shape。
Shape.java
public abstract class Shape { protected DrawAPI drawAPI; protected Shape(DrawAPI drawAPI){ this.drawAPI = drawAPI; } public abstract void draw(); }
步骤 4
创建实现Shape接口的具体类。
Circle.java
public class Circle extends Shape { private int x, y, radius; public Circle(int x, int y, int radius, DrawAPI drawAPI) { super(drawAPI); this.x = x; this.y = y; this.radius = radius; } public void draw() { drawAPI.drawCircle(radius,x,y); } }
步骤 5
使用Shape和DrawAPI类绘制不同颜色的圆。
BridgePatternDemo.java
public class BridgePatternDemo { public static void main(String[] args) { Shape redCircle = new Circle(100,100, 10, new RedCircle()); Shape greenCircle = new Circle(100,100, 10, new GreenCircle()); redCircle.draw(); greenCircle.draw(); } }
步骤 6
验证输出。
Drawing Circle[ color: red, radius: 10, x: 100, 100] Drawing Circle[ color: green, radius: 10, x: 100, 100]
过滤器/标准模式 (Filter/Criteria Pattern)
过滤器模式或标准模式是一种设计模式,它使开发人员能够使用不同的标准过滤一组对象,并通过逻辑运算以解耦的方式将它们链接起来。这种设计模式属于结构型模式,因为它组合了多个标准以获得单个标准。
实现
我们将创建一个Person对象、Criteria接口和实现此接口的具体类,以过滤Person对象的列表。我们的演示类CriteriaPatternDemo使用Criteria对象根据各种标准及其组合来过滤Person对象的列表。
步骤 1
创建一个要应用标准的类。
Person.java
public class Person { private String name; private String gender; private String maritalStatus; public Person(String name,String gender,String maritalStatus){ this.name = name; this.gender = gender; this.maritalStatus = maritalStatus; } public String getName() { return name; } public String getGender() { return gender; } public String getMaritalStatus() { return maritalStatus; } }
步骤 2
为Criteria创建接口。
Criteria.java
import java.util.List; public interface Criteria { public List<Person> meetCriteria(List<Person> persons); }
步骤 3
创建实现Criteria接口的具体类。
CriteriaMale.java
import java.util.ArrayList; import java.util.List; public class CriteriaMale implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> malePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getGender().equalsIgnoreCase("MALE")){ malePersons.add(person); } } return malePersons; } }
CriteriaFemale.java
import java.util.ArrayList; import java.util.List; public class CriteriaFemale implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> femalePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getGender().equalsIgnoreCase("FEMALE")){ femalePersons.add(person); } } return femalePersons; } }
CriteriaSingle.java
import java.util.ArrayList; import java.util.List; public class CriteriaSingle implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> singlePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){ singlePersons.add(person); } } return singlePersons; } }
AndCriteria.java
import java.util.List; public class AndCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public AndCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> firstCriteriaPersons = criteria.meetCriteria(persons); return otherCriteria.meetCriteria(firstCriteriaPersons); } }
OrCriteria.java
import java.util.List; public class AndCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public AndCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> firstCriteriaItems = criteria.meetCriteria(persons); List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons); for (Person person : otherCriteriaItems) { if(!firstCriteriaItems.contains(person)){ firstCriteriaItems.add(person); } } return firstCriteriaItems; } }
步骤4
使用不同的Criteria及其组合来过滤人员。
CriteriaPatternDemo.java
import java.util.ArrayList; import java.util.List; public class CriteriaPatternDemo { public static void main(String[] args) { List<Person> persons = new ArrayList<Person>(); persons.add(new Person("Robert","Male", "Single")); persons.add(new Person("John","Male", "Married")); persons.add(new Person("Laura","Female", "Married")); persons.add(new Person("Diana","Female", "Single")); persons.add(new Person("Mike","Male", "Single")); persons.add(new Person("Bobby","Male", "Single")); Criteria male = new CriteriaMale(); Criteria female = new CriteriaFemale(); Criteria single = new CriteriaSingle(); Criteria singleMale = new AndCriteria(single, male); Criteria singleOrFemale = new OrCriteria(single, female); System.out.println("Males: "); printPersons(male.meetCriteria(persons)); System.out.println("\nFemales: "); printPersons(female.meetCriteria(persons)); System.out.println("\nSingle Males: "); printPersons(singleMale.meetCriteria(persons)); System.out.println("\nSingle Or Females: "); printPersons(singleOrFemale.meetCriteria(persons)); } public static void printPersons(List<Person> persons){ for (Person person : persons) { System.out.println("Person : [ Name : " + person.getName() +", Gender : " + person.getGender() +", Marital Status : " + person.getMaritalStatus() +" ]"); } } }
步骤 5
验证输出。
Males: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : John, Gender : Male, Marital Status : Married ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Females: Person : [ Name : Laura, Gender : Female, Marital Status : Married ] Person : [ Name : Diana, Gender : Female, Marital Status : Single ] Single Males: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Single Or Females: Person : [ Name : Robert, Gender : Male, Marital Status : Single ] Person : [ Name : Diana, Gender : Female, Marital Status : Single ] Person : [ Name : Mike, Gender : Male, Marital Status : Single ] Person : [ Name : Bobby, Gender : Male, Marital Status : Single ] Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
组合模式 (Composite Pattern)
组合模式用于我们需要以类似于单个对象的方式处理一组对象的情况。组合模式根据树结构组成对象,以表示部分和整体层次结构。这种设计模式属于结构型模式,因为它创建一组对象的树结构。
此模式创建一个类,其中包含其自身对象组。此类提供修改其相同对象组的方法。
我们将通过以下示例演示组合模式的使用,该示例显示了一个组织的员工层次结构。
实现
我们有一个类Employee,它充当组合模式参与者类。我们的演示类CompositePatternDemo将使用Employee类添加部门级别层次结构并打印所有员工。
步骤 1
创建包含Employee对象列表的Employee类。
Employee.java
import java.util.ArrayList; import java.util.List; public class Employee { private String name; private String dept; private int salary; private List<Employee> subordinates; // constructor public Employee(String name,String dept, int sal) { this.name = name; this.dept = dept; this.salary = sal; subordinates = new ArrayList<Employee>(); } public void add(Employee e) { subordinates.add(e); } public void remove(Employee e) { subordinates.remove(e); } public List<Employee> getSubordinates(){ return subordinates; } public String toString(){ return ("Employee :[ Name : "+ name +", dept : "+ dept + ", salary :" + salary+" ]"); } }
步骤 2
使用Employee类创建和打印员工层次结构。
CompositePatternDemo.java
public class CompositePatternDemo { public static void main(String[] args) { Employee CEO = new Employee("John","CEO", 30000); Employee headSales = new Employee("Robert","Head Sales", 20000); Employee headMarketing = new Employee("Michel","Head Marketing", 20000); Employee clerk1 = new Employee("Laura","Marketing", 10000); Employee clerk2 = new Employee("Bob","Marketing", 10000); Employee salesExecutive1 = new Employee("Richard","Sales", 10000); Employee salesExecutive2 = new Employee("Rob","Sales", 10000); CEO.add(headSales); CEO.add(headMarketing); headSales.add(salesExecutive1); headSales.add(salesExecutive2); headMarketing.add(clerk1); headMarketing.add(clerk2); //print all employees of the organization System.out.println(CEO); for (Employee headEmployee : CEO.getSubordinates()) { System.out.println(headEmployee); for (Employee employee : headEmployee.getSubordinates()) { System.out.println(employee); } } } }
步骤 3
验证输出。
Employee :[ Name : John, dept : CEO, salary :30000 ] Employee :[ Name : Robert, dept : Head Sales, salary :20000 ] Employee :[ Name : Richard, dept : Sales, salary :10000 ] Employee :[ Name : Rob, dept : Sales, salary :10000 ] Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ] Employee :[ Name : Laura, dept : Marketing, salary :10000 ] Employee :[ Name : Bob, dept : Marketing, salary :10000 ]
装饰器模式 (Decorator Pattern)
装饰器模式允许在不改变其结构的情况下向现有对象添加新功能。这种设计模式属于结构型模式,因为它充当现有类的包装器。
此模式创建一个装饰器类,该类包装原始类并提供附加功能,同时保持类方法签名不变。
我们将通过以下示例演示装饰器模式的使用,在该示例中,我们将用某种颜色装饰形状而无需更改形状类。
实现
我们将创建一个Shape接口和实现Shape接口的具体类。然后,我们创建一个抽象装饰器类ShapeDecorator,它实现Shape接口并将其Shape对象作为其实例变量。
RedShapeDecorator是实现ShapeDecorator的具体类。
我们的演示类DecoratorPatternDemo将使用RedShapeDecorator来装饰Shape对象。
步骤 1
创建一个接口。
Shape.java
public interface Shape { void draw(); }
步骤 2
创建实现同一接口的具体类。
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } }
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }
步骤 3
创建实现Shape接口的抽象装饰器类。
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
步骤 4
创建扩展ShapeDecorator类的具体装饰器类。
RedShapeDecorator.java
public 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"); } }
步骤 5
使用RedShapeDecorator装饰Shape对象。
DecoratorPatternDemo.java
public class DecoratorPatternDemo { public static void main(String[] args) { Shape circle = new Circle(); Shape redCircle = new RedShapeDecorator(new Circle()); Shape redRectangle = new RedShapeDecorator(new Rectangle()); System.out.println("Circle with normal border"); circle.draw(); System.out.println("\nCircle of red border"); redCircle.draw(); System.out.println("\nRectangle of red border"); redRectangle.draw(); } }
步骤 6
验证输出。
Circle with normal border Shape: Circle Circle of red border Shape: Circle Border Color: Red Rectangle of red border Shape: Rectangle Border Color: Red
外观模式 (Facade Pattern)
外观模式隐藏了系统的复杂性,并向客户端提供了一个接口,客户端可以使用该接口访问系统。这种设计模式属于结构型模式,因为它向现有系统添加了一个接口以隐藏其复杂性。
此模式涉及一个类,该类提供客户端所需的简化方法,并将调用委托给现有系统类的方 法。
实现
我们将创建一个Shape接口和实现Shape接口的具体类。下一步定义一个外观类ShapeMaker。
ShapeMaker类使用具体类将用户调用委托给这些类。我们的演示类FacadePatternDemo将使用ShapeMaker类显示结果。
步骤 1
创建一个接口。
Shape.java
public interface Shape { void draw(); }
步骤 2
创建实现同一接口的具体类。
Rectangle.java
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle::draw()"); } }
Square.java
public class Square implements Shape { @Override public void draw() { System.out.println("Square::draw()"); } }
Circle.java
public class Circle implements Shape { @Override public void draw() { System.out.println("Circle::draw()"); } }
步骤 3
创建一个外观类。
ShapeMaker.java
public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker() { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void drawCircle(){ circle.draw(); } public void drawRectangle(){ rectangle.draw(); } public void drawSquare(){ square.draw(); } }
步骤 4
使用外观绘制各种形状。
FacadePatternDemo.java
public class FacadePatternDemo { public static void main(String[] args) { ShapeMaker shapeMaker = new ShapeMaker(); shapeMaker.drawCircle(); shapeMaker.drawRectangle(); shapeMaker.drawSquare(); } }
步骤 5
验证输出。
Circle::draw() Rectangle::draw() Square::draw()
享元模式 (Flyweight Pattern)
享元模式主要用于减少创建的对象数量,以减少内存占用并提高性能。这种设计模式属于结构型模式,因为它提供减少对象数量从而改进应用程序所需对象结构的方法。
享元模式尝试通过存储已经存在的类似对象来重用它们,并在找不到匹配的对象时创建新对象。我们将通过绘制 20 个不同位置的圆来演示此模式,但我们只创建 5 个对象。只有 5 种颜色可用,因此颜色属性用于检查已经存在的Circle对象。
实现
我们将创建一个Shape接口和实现Shape接口的具体类Circle。下一步定义一个工厂类ShapeFactory。
ShapeFactory有一个Circle的HashMap,其键是Circle对象的颜色。每当请求创建特定颜色的圆到ShapeFactory时。ShapeFactory检查其HashMap中的圆对象,如果找到Circle的对象,则返回该对象;否则,将创建一个新对象,将其存储在hashmap中以供将来使用,并将其返回给客户端。
我们的演示类FlyWeightPatternDemo将使用ShapeFactory获取Shape对象。它将信息(红色/绿色/蓝色/黑色/白色)传递给ShapeFactory以获取其所需的所需颜色的圆。
步骤 1
创建一个接口。
Shape.java
public interface Shape { void draw(); }
步骤 2
创建实现相同接口的具体类。
Circle.java
public class Circle implements Shape { private String color; private int x; private int y; private int radius; public Circle(String color){ this.color = color; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setRadius(int radius) { this.radius = radius; } @Override public void draw() { System.out.println("Circle: Draw() [Color : " + color +", x : " + x +", y :" + y +", radius :" + radius); } }
步骤 3
创建一个工厂,根据给定的信息生成具体类的对象。
ShapeFactory.java
import java.util.HashMap; public class ShapeFactory { // Uncomment the compiler directive line and // javac *.java will compile properly. // @SuppressWarnings("unchecked") private static final HashMap circleMap = new HashMap(); public static Shape getCircle(String color) { Circle circle = (Circle)circleMap.get(color); if(circle == null) { circle = new Circle(color); circleMap.put(color, circle); System.out.println("Creating circle of color : " + color); } return circle; } }
步骤 4
通过传递信息(例如颜色)使用工厂获取具体类的对象。
FlyweightPatternDemo.java
public class FlyweightPatternDemo { private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" }; public static void main(String[] args) { for(int i=0; i < 20; ++i) { Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); circle.setY(getRandomY()); circle.setRadius(100); circle.draw(); } } private static String getRandomColor() { return colors[(int)(Math.random()*colors.length)]; } private static int getRandomX() { return (int)(Math.random()*100 ); } private static int getRandomY() { return (int)(Math.random()*100); } }
步骤 5
验证输出。
Creating circle of color : Black Circle: Draw() [Color : Black, x : 36, y :71, radius :100 Creating circle of color : Green Circle: Draw() [Color : Green, x : 27, y :27, radius :100 Creating circle of color : White Circle: Draw() [Color : White, x : 64, y :10, radius :100 Creating circle of color : Red Circle: Draw() [Color : Red, x : 15, y :44, radius :100 Circle: Draw() [Color : Green, x : 19, y :10, radius :100 Circle: Draw() [Color : Green, x : 94, y :32, radius :100 Circle: Draw() [Color : White, x : 69, y :98, radius :100 Creating circle of color : Blue Circle: Draw() [Color : Blue, x : 13, y :4, radius :100 Circle: Draw() [Color : Green, x : 21, y :21, radius :100 Circle: Draw() [Color : Blue, x : 55, y :86, radius :100 Circle: Draw() [Color : White, x : 90, y :70, radius :100 Circle: Draw() [Color : Green, x : 78, y :3, radius :100 Circle: Draw() [Color : Green, x : 64, y :89, radius :100 Circle: Draw() [Color : Blue, x : 3, y :91, radius :100 Circle: Draw() [Color : Blue, x : 62, y :82, radius :100 Circle: Draw() [Color : Green, x : 97, y :61, radius :100 Circle: Draw() [Color : Green, x : 86, y :12, radius :100 Circle: Draw() [Color : Green, x : 38, y :93, radius :100 Circle: Draw() [Color : Red, x : 76, y :82, radius :100 Circle: Draw() [Color : Blue, x : 95, y :82, radius :100
代理模式 (Proxy Pattern)
在代理模式中,一个类代表另一个类的功能。这种设计模式属于结构型模式。
在代理模式中,我们创建一个包含原始对象的代理对象,以便将其功能与外部世界交互。
实现
我们将创建一个Image接口以及实现Image接口的具体类。ProxyImage是一个代理类,用于减少RealImage对象加载时的内存占用。
ProxyPatternDemo,我们的演示类将使用ProxyImage来获取Image对象,并在需要时加载和显示。
步骤 1
创建一个接口。
Image.java
public interface Image { void display(); }
步骤 2
创建实现同一接口的具体类。
RealImage.java
public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } }
ProxyImage.java
public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } }
步骤 3
根据需要使用ProxyImage获取RealImage类的对象。
ProxyPatternDemo.java
public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test_10mb.jpg"); //image will be loaded from disk image.display(); System.out.println(""); //image will not be loaded from disk image.display(); } }
步骤 4
验证输出。
Loading test_10mb.jpg Displaying test_10mb.jpg Displaying test_10mb.jpg
责任链模式
顾名思义,责任链模式为请求创建了一个接收者对象的链。这种模式根据请求类型解耦了请求的发起者和接收者。这种模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象无法处理请求,则将其传递给下一个接收者,依此类推。
实现
我们创建了一个抽象类AbstractLogger,它具有日志记录级别。然后,我们创建了三种扩展AbstractLogger的日志记录器类型。每个日志记录器都会检查消息级别与其级别是否匹配,如果匹配则打印,否则不打印并将消息传递给其下一个日志记录器。
步骤 1
创建一个抽象日志记录器类。
AbstractLogger.java
public abstract class AbstractLogger { public static int INFO = 1; public static int DEBUG = 2; public static int ERROR = 3; protected int level; //next element in chain or responsibility protected AbstractLogger nextLogger; public void setNextLogger(AbstractLogger nextLogger){ this.nextLogger = nextLogger; } public void logMessage(int level, String message){ if(this.level <= level){ write(message); } if(nextLogger !=null){ nextLogger.logMessage(level, message); } } abstract protected void write(String message); }
步骤 2
创建扩展日志记录器的具体类。
ConsoleLogger.java
public class ConsoleLogger extends AbstractLogger { public ConsoleLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("Standard Console::Logger: " + message); } }
ErrorLogger.java
public class ErrorLogger extends AbstractLogger { public ErrorLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("Error Console::Logger: " + message); } }
FileLogger.java
public class FileLogger extends AbstractLogger { public FileLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("File::Logger: " + message); } }
步骤 3
创建不同类型的日志记录器。为它们分配错误级别并在每个日志记录器中设置下一个日志记录器。每个日志记录器中的下一个日志记录器代表链的一部分。
ChainPatternDemo.java
public class ChainPatternDemo { private static AbstractLogger getChainOfLoggers(){ AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR); AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG); AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO); errorLogger.setNextLogger(fileLogger); fileLogger.setNextLogger(consoleLogger); return errorLogger; } public static void main(String[] args) { AbstractLogger loggerChain = getChainOfLoggers(); loggerChain.logMessage(AbstractLogger.INFO, "This is an information."); loggerChain.logMessage(AbstractLogger.DEBUG, "This is an debug level information."); loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information."); } }
步骤 4
验证输出。
Standard Console::Logger: This is an information. File::Logger: This is an debug level information. Standard Console::Logger: This is an debug level information. Error Console::Logger: This is an error information. File::Logger: This is an error information. Standard Console::Logger: This is an error information.
命令模式
命令模式是一种数据驱动型设计模式,属于行为型模式类别。请求被封装在一个对象中作为命令,并传递给调用者对象。调用者对象查找可以处理此命令的适当对象,并将命令传递给相应的对象,该对象执行命令。
实现
我们创建了一个Order接口,它充当命令。我们创建了一个Stock类,它充当请求。我们创建了实现Order接口的具体命令类BuyStock和SellStock,它们将执行实际的命令处理。创建了一个Broker类,它充当调用者对象。它可以接受订单并下订单。
Broker对象使用命令模式来识别哪个对象将根据命令类型执行哪个命令。CommandPatternDemo,我们的演示类将使用Broker类来演示命令模式。
步骤 1
创建一个命令接口。
Order.java
public interface Order { void execute(); }
步骤 2
创建一个请求类。
Stock.java
public class Stock { private String name = "ABC"; private int quantity = 10; public void buy(){ System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] bought"); } public void sell(){ System.out.println("Stock [ Name: "+name+", Quantity: " + quantity +" ] sold"); } }
步骤 3
创建实现Order接口的具体类。
BuyStock.java
public class BuyStock implements Order { private Stock abcStock; public BuyStock(Stock abcStock){ this.abcStock = abcStock; } public void execute() { abcStock.buy(); } }
SellStock.java
public class SellStock implements Order { private Stock abcStock; public SellStock(Stock abcStock){ this.abcStock = abcStock; } public void execute() { abcStock.sell(); } }
步骤 4
创建命令调用者类。
Broker.java
import java.util.ArrayList; import java.util.List; public class Broker { private List<Order> orderList = new ArrayList<Order>(); public void takeOrder(Order order){ orderList.add(order); } public void placeOrders(){ for (Order order : orderList) { order.execute(); } orderList.clear(); } }
步骤 5
使用Broker类来接收和执行命令。
CommandPatternDemo.java
public class CommandPatternDemo { public static void main(String[] args) { Stock abcStock = new Stock(); BuyStock buyStockOrder = new BuyStock(abcStock); SellStock sellStockOrder = new SellStock(abcStock); Broker broker = new Broker(); broker.takeOrder(buyStockOrder); broker.takeOrder(sellStockOrder); broker.placeOrders(); } }
步骤 6
验证输出。
Stock [ Name: ABC, Quantity: 10 ] bought Stock [ Name: ABC, Quantity: 10 ] sold
解释器模式
解释器模式提供了一种评估语言语法或表达式的途径。这种模式属于行为型模式。这种模式涉及实现一个表达式接口,该接口指示解释特定上下文。这种模式用于SQL解析、符号处理引擎等。
实现
我们将创建一个Expression接口以及实现Expression接口的具体类。定义了一个TerminalExpression类,它充当所讨论上下文的解释器。其他类OrExpression、AndExpression用于创建组合表达式。
InterpreterPatternDemo,我们的演示类将使用Expression类来创建规则并演示表达式的解析。
步骤 1
创建一个表达式接口。
Expression.java
public interface Expression { public boolean interpret(String context); }
步骤 2
创建实现上述接口的具体类。
TerminalExpression.java
public class TerminalExpression implements Expression { private String data; public TerminalExpression(String data){ this.data = data; } @Override public boolean interpret(String context) { if(context.contains(data)){ return true; } return false; } }
OrExpression.java
public class OrExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context); } }
AndExpression.java
public class AndExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context); } }
步骤 3
InterpreterPatternDemo使用Expression类创建规则,然后解析它们。
InterpreterPatternDemo.java
public class InterpreterPatternDemo { //Rule: Robert and John are male public static Expression getMaleExpression(){ Expression robert = new TerminalExpression("Robert"); Expression john = new TerminalExpression("John"); return new OrExpression(robert, john); } //Rule: Julie is a married women public static Expression getMarriedWomanExpression(){ Expression julie = new TerminalExpression("Julie"); Expression married = new TerminalExpression("Married"); return new AndExpression(julie, married); } public static void main(String[] args) { Expression isMale = getMaleExpression(); Expression isMarriedWoman = getMarriedWomanExpression(); System.out.println("John is male? " + isMale.interpret("John")); System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie")); } }
步骤 4
验证输出。
John is male? true Julie is a married women? true
迭代器模式
迭代器模式在Java和.Net编程环境中非常常用。这种模式用于以顺序方式访问集合对象的元素,而无需了解其底层表示。
迭代器模式属于行为型模式类别。
实现
我们将创建一个Iterator接口,它描述导航方法,以及一个Container接口,它返回迭代器。实现Container接口的具体类将负责实现Iterator接口并使用它。
IteratorPatternDemo,我们的演示类将使用NamesRepository(一个具体的类实现)来打印存储在NamesRepository中的集合Names。
步骤 1
创建接口。
Iterator.java
public interface Iterator { public boolean hasNext(); public Object next(); }
Container.java
public interface Container { public Iterator getIterator(); }
步骤 2
创建实现Container接口的具体类。此类具有内部类NameIterator,它实现了Iterator接口。
NameRepository.java
public class NameRepository implements Container { public String names[] = {"Robert" , "John" ,"Julie" , "Lora"}; @Override public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator { int index; @Override public boolean hasNext() { if(index < names.length){ return true; } return false; } @Override public Object next() { if(this.hasNext()){ return names[index++]; } return null; } } }
步骤 3
使用NameRepository获取迭代器并打印名称。
IteratorPatternDemo.java
public class IteratorPatternDemo { public static void main(String[] args) { NameRepository namesRepository = new NameRepository(); for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){ String name = (String)iter.next(); System.out.println("Name : " + name); } } }
步骤 4
验证输出。
Name : Robert Name : John Name : Julie Name : Lora
中介者模式
中介者模式用于减少多个对象或类之间的通信复杂性。这种模式提供了一个中介者类,该类通常处理不同类之间的所有通信,并通过松耦合支持代码的易维护性。中介者模式属于行为型模式类别。
实现
我们通过聊天室的示例演示中介者模式,在聊天室中,多个用户可以向聊天室发送消息,而聊天室负责向所有用户显示消息。我们创建了两个类ChatRoom和User。User对象将使用ChatRoom方法共享其消息。
MediatorPatternDemo,我们的演示类将使用User对象来显示它们之间的通信。
步骤 1
创建中介者类。
ChatRoom.java
import java.util.Date; public class ChatRoom { public static void showMessage(User user, String message){ System.out.println(new Date().toString() + " [" + user.getName() +"] : " + message); } }
步骤 2
创建用户类
User.java
public class User { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public User(String name){ this.name = name; } public void sendMessage(String message){ ChatRoom.showMessage(this,message); } }
步骤 3
使用User对象来显示它们之间的通信。
MediatorPatternDemo.java
public class MediatorPatternDemo { public static void main(String[] args) { User robert = new User("Robert"); User john = new User("John"); robert.sendMessage("Hi! John!"); john.sendMessage("Hello! Robert!"); } }
步骤 4
验证输出。
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John! Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!
备忘录模式
备忘录模式用于在我们需要将对象的狀態还原到之前的狀態时使用。备忘录模式属于行为型模式类别。
实现
备忘录模式使用三个参与者类。备忘录包含要还原的对象的狀態。发起者创建并将狀態存储在备忘录对象中,而管理者对象负责从备忘录中还原对象狀態。我们创建了Memento、Originator和CareTaker类。
MementoPatternDemo,我们的演示类将使用CareTaker和Originator对象来显示对象狀態的还原。
步骤 1
创建备忘录类。
Memento.java
public class Memento { private String state; public Memento(String state){ this.state = state; } public String getState(){ return state; } }
步骤 2
创建发起者类
Originator.java
public class Originator { private String state; public void setState(String state){ this.state = state; } public String getState(){ return state; } public Memento saveStateToMemento(){ return new Memento(state); } public void getStateFromMemento(Memento Memento){ state = memento.getState(); } }
步骤 3
创建管理者类
CareTaker.java
import java.util.ArrayList; import java.util.List; public class CareTaker { private List<Memento> mementoList = new ArrayList<Memento>(); public void add(Memento state){ mementoList.add(state); } public Memento get(int index){ return mementoList.get(index); } }
步骤 4
使用CareTaker和Originator对象。
MementoPatternDemo.java
public class MementoPatternDemo { public static void main(String[] args) { Originator originator = new Originator(); CareTaker careTaker = new CareTaker(); originator.setState("State #1"); originator.setState("State #2"); careTaker.add(originator.saveStateToMemento()); originator.setState("State #3"); careTaker.add(originator.saveStateToMemento()); originator.setState("State #4"); System.out.println("Current State: " + originator.getState()); originator.getStateFromMemento(careTaker.get(0)); System.out.println("First saved State: " + originator.getState()); originator.getStateFromMemento(careTaker.get(1)); System.out.println("Second saved State: " + originator.getState()); } }
步骤 5
验证输出。
Current State: State #4 First saved State: State #2 Second saved State: State #3
观察者模式
当对象之间存在一对多关系时,例如,如果修改一个对象,则需要自动通知其依赖对象,则使用观察者模式。观察者模式属于行为型模式类别。
实现
观察者模式使用三个参与者类:主题、观察者和客户端。主题,一个具有附加和分离观察者到客户端对象的方法的对象。我们创建了Subject类、Observer抽象类以及扩展Observer抽象类的具体类。
ObserverPatternDemo,我们的演示类将使用Subject和具体类对象来演示观察者模式。
步骤 1
创建主题类。
Subject.java
import java.util.ArrayList; import java.util.List; public class Subject { private List<Observer> observers = new ArrayList<Observer>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for (Observer observer : observers) { observer.update(); } } }
步骤 2
创建观察者类。
Observer.java
public abstract class Observer { protected Subject subject; public abstract void update(); }
步骤 3
创建具体的观察者类
BinaryObserver.java
public class BinaryObserver extends Observer{ public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); } }
OctalObserver.java
public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); } }
HexaObserver.java
public class HexaObserver extends Observer{ public HexaObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); } }
步骤 4
使用Subject和具体的观察者对象。
ObserverPatternDemo.java
public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); System.out.println("First state change: 15"); subject.setState(15); System.out.println("Second state change: 10"); subject.setState(10); } }
步骤 5
验证输出。
First state change: 15 Hex String: F Octal String: 17 Binary String: 1111 Second state change: 10 Hex String: A Octal String: 12 Binary String: 1010
状态模式
在状态模式中,类的行为根据其状态而改变。这种设计模式属于行为模式。
在状态模式中,我们创建表示各种状态的对象以及一个上下文对象,其行为随着其状态对象的改变而改变。
实现
我们将创建一个State接口,定义一个操作以及实现State接口的具体状态类。Context是一个包含状态的类。
StaePatternDemo,我们的演示类将使用Context和状态对象来演示基于其所处的状态类型而改变的上下文行为。
步骤 1
创建一个接口。
Image.java
public interface State { public void doAction(Context context); }
步骤 2
创建实现同一接口的具体类。
StartState.java
public class StartState implements State { public void doAction(Context context) { System.out.println("Player is in start state"); context.setState(this); } public String toString(){ return "Start State"; } }
StopState.java
public class StopState implements State { public void doAction(Context context) { System.out.println("Player is in stop state"); context.setState(this); } public String toString(){ return "Stop State"; } }
步骤 3
创建Context类。
Context.java
public class Context { private State state; public Context(){ state = null; } public void setState(State state){ this.state = state; } public State getState(){ return state; } }
步骤 4
使用Context查看当State改变时行为的变化。
StatePatternDemo.java
public class StatePatternDemo { public static void main(String[] args) { Context context = new Context(); StartState startState = new StartState(); startState.doAction(context); System.out.println(context.getState().toString()); StopState stopState = new StopState(); stopState.doAction(context); System.out.println(context.getState().toString()); } }
步骤 5
验证输出。
Player is in start state Start State Player is in stop state Stop State
空对象模式
在空对象模式中,空对象替换了对NULL对象实例的检查。我们无需对null值进行if检查,空对象反映了不执行任何操作的关系。这种空对象也可用于在数据不可用时提供默认行为。
在空对象模式中,我们创建一个抽象类,指定要执行的各种操作,具体类扩展此类,以及一个空对象类,提供此类的什么也不做的实现,并在我们需要检查null值的地方无缝使用。
实现
我们将创建一个AbstractCustomer抽象类,定义客户的名称以及扩展AbstractCustomer类的具体类。创建了一个工厂类CustomerFactory,根据传递给它的客户名称返回RealCustomer或NullCustomer对象。
NullPatternDemo,我们的演示类将使用CustomerFactory来演示空对象模式的使用。
步骤 1
创建一个抽象类。
AbstractCustomer.java
public abstract class AbstractCustomer { protected String name; public abstract boolean isNil(); public abstract String getName(); }
步骤 2
创建扩展上述类的具体类。
RealCustomer.java
public class RealCustomer extends AbstractCustomer { public RealCustomer(String name) { this.name = name; } @Override public String getName() { return name; } @Override public boolean isNil() { return false; } }
NullCustomer.java
public class NullCustomer extends AbstractCustomer { @Override public String getName() { return "Not Available in Customer Database"; } @Override public boolean isNil() { return true; } }
步骤 3
创建CustomerFactory类。
CustomerFactory.java
public class CustomerFactory { public static final String[] names = {"Rob", "Joe", "Julie"}; public static AbstractCustomer getCustomer(String name){ for (int i = 0; i < names.length; i++) { if (names[i].equalsIgnoreCase(name)){ return new RealCustomer(name); } } return new NullCustomer(); } }
步骤 4
使用CustomerFactory根据传递给它的客户名称获取RealCustomer或NullCustomer对象。
NullPatternDemo.java
public class NullPatternDemo { public static void main(String[] args) { AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob"); AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob"); AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie"); AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura"); System.out.println("Customers"); System.out.println(customer1.getName()); System.out.println(customer2.getName()); System.out.println(customer3.getName()); System.out.println(customer4.getName()); } }
步骤 5
验证输出。
Customers Rob Not Available in Customer Database Julie Not Available in Customer Database
策略模式
在策略模式中,可以在运行时更改类的行为或其算法。这种设计模式属于行为模式。
在策略模式中,我们创建表示各种策略的对象以及一个上下文对象,其行为根据其策略对象而变化。策略对象更改上下文对象的执行算法。
实现
我们将创建一个Strategy接口,定义一个动作以及实现Strategy接口的具体策略类。Context是一个使用策略的类。
StrategyPatternDemo,我们的演示类将使用Context和策略对象来演示基于其部署或使用的策略的Context行为变化。
步骤 1
创建一个接口。
Strategy.java
public interface Strategy { public int doOperation(int num1, int num2); }
步骤 2
创建实现同一接口的具体类。
OperationAdd.java
public class OperationAdd implements Strategy{ @Override public int doOperation(int num1, int num2) { return num1 + num2; } }
OperationSubstract.java
public class OperationSubstract implements Strategy{ @Override public int doOperation(int num1, int num2) { return num1 - num2; } }
OperationMultiply.java
public class OperationMultiply implements Strategy{ @Override public int doOperation(int num1, int num2) { return num1 * num2; } }
步骤 3
创建Context类。
Context.java
public class Context { private Strategy strategy; public Context(Strategy strategy){ this.strategy = strategy; } public int executeStrategy(int num1, int num2){ return strategy.doOperation(num1, num2); } }
步骤 4
使用Context查看其更改Strategy时行为的变化。
StatePatternDemo.java
public class StrategyPatternDemo { public static void main(String[] args) { Context context = new Context(new OperationAdd()); System.out.println("10 + 5 = " + context.executeStrategy(10, 5)); context = new Context(new OperationSubstract()); System.out.println("10 - 5 = " + context.executeStrategy(10, 5)); context = new Context(new OperationMultiply()); System.out.println("10 * 5 = " + context.executeStrategy(10, 5)); } }
步骤 5
验证输出。
10 + 5 = 15 10 - 5 = 5 10 * 5 = 50
模板模式(Template Pattern)
在模板模式中,抽象类公开定义的方法/模板来执行其方法。它的子类可以根据需要覆盖方法实现,但调用方式必须与抽象类定义的方式相同。此模式属于行为模式类别。
实现
我们将创建一个Game抽象类,定义带有模板方法的操作,该模板方法设置为final,因此无法被覆盖。Cricket和Football是扩展Game并覆盖其方法的具体类。
TemplatePatternDemo,我们的演示类将使用Game来演示模板模式的使用。
步骤 1
创建一个带有最终模板方法的抽象类。
Game.java
public abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); //template method public final void play(){ //initialize the game initialize(); //start game startPlay(); //end game endPlay(); } }
步骤 2
创建扩展上述类的具体类。
Cricket.java
public class Cricket extends Game { @Override void endPlay() { System.out.println("Cricket Game Finished!"); } @Override void initialize() { System.out.println("Cricket Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Cricket Game Started. Enjoy the game!"); } }
Football.java
public class Football extends Game { @Override void endPlay() { System.out.println("Football Game Finished!"); } @Override void initialize() { System.out.println("Football Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } }
步骤 3
使用Game的模板方法play()来演示定义的游戏玩法。
TemplatePatternDemo.java
public class TemplatePatternDemo { public static void main(String[] args) { Game game = new Cricket(); game.play(); System.out.println(); game = new Football(); game.play(); } }
步骤 4
验证输出。
Cricket Game Initialized! Start playing. Cricket Game Started. Enjoy the game! Cricket Game Finished! Football Game Initialized! Start playing. Football Game Started. Enjoy the game! Football Game Finished!
访问者模式(Visitor Pattern)
在访问者模式中,我们使用一个访问者类来改变元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者的变化而变化。此模式属于行为模式类别。根据该模式,元素对象必须接受访问者对象,以便访问者对象处理元素对象的操作。
实现
我们将创建一个ComputerPart接口,定义accept操作。Keyboard、Mouse、Monitor和Computer是实现ComputerPart接口的具体类。我们将定义另一个接口ComputerPartVisitor,它将定义访问者类的操作。Computer使用具体的访问者来执行相应的操作。
VisitorPatternDemo,我们的演示类将使用Computer和ComputerPartVisitor类来演示访问者模式的使用。
步骤 1
定义一个接口来表示元素。
ComputerPart.java
public interface class ComputerPart { public void accept(ComputerPartVisitor computerPartVisitor); }
步骤 2
创建扩展上述类的具体类。
Keyboard.java
public class Keyboard implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
Monitor.java
public class Monitor implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
Mouse.java
public class Mouse implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
Computer.java
public class Computer implements ComputerPart { ComputerPart[] parts; public Computer(){ parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()}; } @Override public void accept(ComputerPartVisitor computerPartVisitor) { for (int i = 0; i < parts.length; i++) { parts[i].accept(computerPartVisitor); } computerPartVisitor.visit(this); } }
步骤 3
定义一个接口来表示访问者。
ComputerPartVisitor.java
public interface ComputerPartVisitor { public void visit(Computer computer); public void visit(Mouse mouse); public void visit(Keyboard keyboard); public void visit(Monitor monitor); }
步骤 4
创建实现上述类的具体访问者。
ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements ComputerPartVisitor { @Override public void visit(Computer computer) { System.out.println("Displaying Computer."); } @Override public void visit(Mouse mouse) { System.out.println("Displaying Mouse."); } @Override public void visit(Keyboard keyboard) { System.out.println("Displaying Keyboard."); } @Override public void visit(Monitor monitor) { System.out.println("Displaying Monitor."); } }
步骤 5
使用ComputerPartDisplayVisitor来显示Computer的部件。
VisitorPatternDemo.java
public class VisitorPatternDemo { public static void main(String[] args) { ComputerPart computer = new Computer(); computer.accept(new ComputerPartDisplayVisitor()); } }
步骤 6
验证输出。
Displaying Mouse. Displaying Keyboard. Displaying Monitor. Displaying Computer.
MVC模式
MVC模式代表模型-视图-控制器模式。此模式用于分离应用程序的关注点。
模型(Model) - 模型表示承载数据的对象或JAVA POJO。如果其数据发生更改,它还可以具有更新控制器的逻辑。
视图(View) - 视图表示模型包含数据的可视化。
控制器(Controller) - 控制器同时作用于模型和视图。它控制数据流入模型对象,并在数据更改时更新视图。它使视图和模型保持分离。
实现
我们将创建一个充当模型的Student对象。StudentView将是一个可以在控制台上打印学生详细信息的视图类,而StudentController是负责将数据存储在Student对象中并相应地更新视图StudentView的控制器类。
MVCPatternDemo,我们的演示类将使用StudentController来演示MVC模式的使用。
步骤 1
创建模型。
Student.java
public class Student { private String rollNo; private String name; public String getRollNo() { return rollNo; } public void setRollNo(String rollNo) { this.rollNo = rollNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
步骤 2
创建视图。
StudentView.java
public class StudentView { public void printStudentDetails(String studentName, String studentRollNo){ System.out.println("Student: "); System.out.println("Name: " + studentName); System.out.println("Roll No: " + studentRollNo); } }
步骤 3
创建控制器。
StudentController.java
public class StudentController { private Student model; private StudentView view; public StudentController(Student model, StudentView view){ this.model = model; this.view = view; } public void setStudentName(String name){ model.setName(name); } public String getStudentName(){ return model.getName(); } public void setStudentRollNo(String rollNo){ model.setRollNo(rollNo); } public String getStudentRollNo(){ return model.getRollNo(); } public void updateView(){ view.printStudentDetails(model.getName(), model.getRollNo()); } }
步骤 4
使用StudentController方法来演示MVC设计模式的使用。
MVCPatternDemo.java
public class MVCPatternDemo { public static void main(String[] args) { //fetch student record based on his roll no from the database Student model = retriveStudentFromDatabase(); //Create a view : to write student details on console StudentView view = new StudentView(); StudentController controller = new StudentController(model, view); controller.updateView(); //update model data controller.setStudentName("John"); controller.updateView(); } private static Student retriveStudentFromDatabase(){ Student student = new Student(); student.setName("Robert"); student.setRollNo("10"); return student; } }
步骤 5
验证输出。
Student: Name: Robert Roll No: 10 Student: Name: Julie Roll No: 10
业务代表模式
业务委托模式用于解耦表示层和业务层。它基本上用于减少表示层代码中对业务层代码的通信或远程查找功能。在业务层中,我们有以下实体。
客户端(Client) - 表示层代码可以是JSP、servlet或UI Java代码。
业务委托(Business Delegate) - 客户端实体访问业务服务方法的单一入口点类。
查找服务(LookUp Service) - 查找服务对象负责获取相关的业务实现,并向业务委托对象提供业务对象访问。
业务服务(Business Service) - 业务服务接口。具体类实现此业务服务以提供实际的业务实现逻辑。
实现
我们将创建一个Client、BusinessDelegate、BusinessService、LookUpService、JMSService和EJBService,分别代表业务委托模式的各种实体。
BusinessDelegatePatternDemo,我们的演示类将使用BusinessDelegate和Client来演示业务委托模式的使用。
步骤 1
创建BusinessService接口。
BusinessService.java
public interface BusinessService { public void doProcessing(); }
步骤 2
创建具体服务类。
EJBService.java
public class EJBService implements BusinessService { @Override public void doProcessing() { System.out.println("Processing task by invoking EJB Service"); } }
JMSService.java
public class JMSService implements BusinessService { @Override public void doProcessing() { System.out.println("Processing task by invoking JMS Service"); } }
步骤 3
创建业务查找服务。
BusinessLookUp.java
public class BusinessLookUp { public BusinessService getBusinessService(String serviceType){ if(serviceType.equalsIgnoreCase("EJB")){ return new EJBService(); }else { return new JMSService(); } } }
步骤 4
创建业务委托。
BusinessLookUp.java
public class BusinessDelegate { private BusinessLookUp lookupService = new BusinessLookUp(); private BusinessService businessService; private String serviceType; public void setServiceType(String serviceType){ this.serviceType = serviceType; } public void doTask(){ businessService = lookupService.getBusinessService(serviceType); businessService.doProcessing(); } }
步骤 5
创建客户端。
Student.java
public class Client { BusinessDelegate businessService; public Client(BusinessDelegate businessService){ this.businessService = businessService; } public void doTask(){ businessService.doTask(); } }
步骤 6
使用BusinessDelegate和Client类来演示业务委托模式。
BusinessDelegatePatternDemo.java
public class BusinessDelegatePatternDemo { public static void main(String[] args) { BusinessDelegate businessDelegate = new BusinessDelegate(); businessDelegate.setServiceType("EJB"); Client client = new Client(businessDelegate); client.doTask(); businessDelegate.setServiceType("JMS"); client.doTask(); } }
步骤 7
验证输出。
Processing task by invoking EJB Service Processing task by invoking JMS Service
组合实体模式
组合实体模式用于EJB持久化机制。组合实体是一个EJB实体bean,它表示对象的图形。当更新组合实体时,内部依赖的对象bean会自动更新,因为它们由EJB实体bean管理。组合实体bean中的参与者如下。
组合实体(Composite Entity) - 它是主要的实体bean。它可以是粗粒度的,也可以包含粗粒度的对象以用于持久化目的。
粗粒度对象(Coarse-Grained Object) - 此对象包含依赖对象。它有自己的生命周期,也管理依赖对象的生命周期。
依赖对象(Dependent Object) - 依赖对象是一个依赖于粗粒度对象持久化生命周期的对象。
策略(Strategies) - 策略表示如何实现组合实体。
实现
我们将创建一个充当组合实体的CompositeEntity对象。CoarseGrainedObject将是一个包含依赖对象的类。CompositeEntityPatternDemo,我们的演示类将使用Client类来演示组合实体模式的使用。
步骤 1
创建依赖对象。
DependentObject1.java
public class DependentObject1 { private String data; public void setData(String data){ this.data = data; } public String getData(){ return data; } }
DependentObject2.java
public class DependentObject2 { private String data; public void setData(String data){ this.data = data; } public String getData(){ return data; } }
步骤 2
创建粗粒度对象。
CoarseGrainedObject.java
public class CoarseGrainedObject { DependentObject1 do1 = new DependentObject1(); DependentObject2 do2 = new DependentObject2(); public void setData(String data1, String data2){ do1.setData(data1); do2.setData(data2); } public String[] getData(){ return new String[] {do1.getData(),do2.getData()}; } }
步骤 3
创建组合实体。
CompositeEntity.java
public class CompositeEntity { private CoarseGrainedObject cgo = new CoarseGrainedObject(); public void setData(String data1, String data2){ cgo.setData(data1, data2); } public String[] getData(){ return cgo.getData(); } }
步骤 4
创建使用组合实体的客户端类。
Client.java
public class Client { private CompositeEntity compositeEntity = new CompositeEntity(); public void printData(){ for (int i = 0; i < compositeEntity.getData().length; i++) { System.out.println("Data: " + compositeEntity.getData()[i]); } } public void setData(String data1, String data2){ compositeEntity.setData(data1, data2); } }
步骤 5
使用Client来演示组合实体设计模式的使用。
CompositeEntityPatternDemo.java
public class CompositeEntityPatternDemo { public static void main(String[] args) { Client client = new Client(); client.setData("Test", "Data"); client.printData(); client.setData("Second Test", "Data1"); client.printData(); } }
步骤 6
验证输出。
Data: Test Data: Data Data: Second Test Data: Data1
数据访问对象模式
数据访问对象模式或DAO模式用于将低级数据访问API或操作与高级业务服务分离。数据访问对象模式中的参与者如下。
数据访问对象接口(Data Access Object Interface) - 此接口定义要在模型对象上执行的标准操作。
数据访问对象具体类(Data Access Object concrete class) - 此类实现上述接口。此类负责从数据源(可以是数据库/xml或任何其他存储机制)获取数据。
模型对象或值对象(Model Object or Value Object) - 此对象是简单的POJO,包含get/set方法以存储使用DAO类检索的数据。
实现
我们将创建一个充当模型或值对象的Student对象。StudentDao是数据访问对象接口。StudentDaoImpl是实现数据访问对象接口的具体类。DaoPatternDemo,我们的演示类将使用StudentDao来演示数据访问对象模式的使用。
步骤 1
创建值对象。
Student.java
public class Student { private String name; private int rollNo; Student(String name, int rollNo){ this.name = name; this.rollNo = rollNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getRollNo() { return rollNo; } public void setRollNo(int rollNo) { this.rollNo = rollNo; } }
步骤 2
创建数据访问对象接口。
StudentDao.java
import java.util.List; public interface StudentDao { public List<Student> getAllStudents(); public Student getStudent(int rollNo); public void updateStudent(Student student); public void deleteStudent(Student student); }
步骤 3
创建实现上述接口的具体类。
StudentDaoImpl.java
import java.util.ArrayList; import java.util.List; public class StudentDaoImpl implements StudentDao { //list is working as a database List<Student> students; public StudentDaoImpl(){ students = new ArrayList<Student>(); Student student1 = new Student("Robert",0); Student student2 = new Student("John",1); students.add(student1); students.add(student2); } @Override public void deleteStudent(Student student) { students.remove(student.getRollNo()); System.out.println("Student: Roll No " + student.getRollNo() +", deleted from database"); } //retrive list of students from the database @Override public List<Student> getAllStudents() { return students; } @Override public Student getStudent(int rollNo) { return students.get(rollNo); } @Override public void updateStudent(Student student) { students.get(student.getRollNo()).setName(student.getName()); System.out.println("Student: Roll No " + student.getRollNo() +", updated in the database"); } }
步骤 4
使用StudentDao来演示数据访问对象模式的使用。
CompositeEntityPatternDemo.java
public class DaoPatternDemo { public static void main(String[] args) { StudentDao studentDao = new StudentDaoImpl(); //print all students for (Student student : studentDao.getAllStudents()) { System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); } //update student Student student =studentDao.getAllStudents().get(0); student.setName("Michael"); studentDao.updateStudent(student); //get the student studentDao.getStudent(0); System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); } }
步骤 5
验证输出。
Student: [RollNo : 0, Name : Robert ] Student: [RollNo : 1, Name : John ] Student: Roll No 0, updated in the database Student: [RollNo : 0, Name : Michael ]
前端控制器模式
前端控制器设计模式用于提供集中式请求处理机制,以便所有请求都由单个处理程序处理。此处理程序可以执行请求的身份验证/授权/日志记录或跟踪,然后将请求传递给相应的处理程序。此类设计模式的实体如下。
前端控制器(Front Controller) - 应用程序(基于Web/基于桌面)的所有请求的单个处理程序。
调度器(Dispatcher) - 前端控制器可以使用调度器对象,该对象可以将请求调度到相应的特定处理程序。
视图(View) - 视图是发出请求的对象。
实现
我们将创建一个FrontController和Dispatcher,分别充当前端控制器和调度器。HomeView和StudentView表示可以向前端控制器发出请求的各种视图。
FrontControllerPatternDemo,我们的演示类将使用FrontController来演示前端控制器设计模式。
步骤 1
创建视图。
HomeView.java
public class HomeView { public void show(){ System.out.println("Displaying Home Page"); } }
StudentView.java
public class StudentView { public void show(){ System.out.println("Displaying Student Page"); } }
步骤 2
创建调度器。
Dispatcher.java
public class Dispatcher { private StudentView studentView; private HomeView homeView; public Dispatcher(){ studentView = new StudentView(); homeView = new HomeView(); } public void dispatch(String request){ if(request.equalsIgnoreCase("STUDENT")){ studentView.show(); }else{ homeView.show(); } } }
步骤 3
创建FrontController
Context.java
public class FrontController { private Dispatcher dispatcher; public FrontController(){ dispatcher = new Dispatcher(); } private boolean isAuthenticUser(){ System.out.println("User is authenticated successfully."); return true; } private void trackRequest(String request){ System.out.println("Page requested: " + request); } public void dispatchRequest(String request){ //log each request trackRequest(request); //authenticate the user if(isAuthenticUser()){ dispatcher.dispatch(request); } } }
步骤 4
使用FrontController来演示前端控制器设计模式。
FrontControllerPatternDemo.java
public class FrontControllerPatternDemo { public static void main(String[] args) { FrontController frontController = new FrontController(); frontController.dispatchRequest("HOME"); frontController.dispatchRequest("STUDENT"); } }
步骤 5
验证输出。
Page requested: HOME User is authenticated successfully. Displaying Home Page Page requested: STUDENT User is authenticated successfully. Displaying Student Page
拦截过滤器模式
拦截过滤器设计模式用于在希望对应用程序的请求或响应进行一些预处理/后处理时使用。在将请求传递给实际的目标应用程序之前,会定义过滤器并将其应用于请求。过滤器可以执行请求的身份验证/授权/日志记录或跟踪,然后将请求传递给相应的处理程序。此类设计模式的实体如下。
过滤器(Filter) - 执行请求处理程序请求执行之前或之后某些任务的过滤器。
过滤器链(Filter Chain) - 过滤器链包含多个过滤器,并帮助按定义的顺序在目标上执行它们。
目标(Target) - 目标对象是请求处理程序
过滤器管理器(Filter Manager) - 过滤器管理器管理过滤器和过滤器链。
客户端(Client) - 客户端是向目标对象发送请求的对象。
实现
我们将创建一个FilterChain、FilterManager、Target、Client作为代表我们实体的各种对象。AuthenticationFilter和DebugFilter表示具体的过滤器。
InterceptingFilterDemo,我们的演示类将使用Client来演示拦截过滤器设计模式。
步骤 1
创建过滤器接口。
Filter.java
public interface Filter { public void execute(String request); }
步骤 2
创建具体过滤器。
AuthenticationFilter.java
public class AuthenticationFilter implements Filter { public void execute(String request){ System.out.println("Authenticating request: " + request); } }
DebugFilter.java
public class DebugFilter implements Filter { public void execute(String request){ System.out.println("request log: " + request); } }
步骤 3
创建目标
Target.java
public class Target { public void execute(String request){ System.out.println("Executing request: " + request); } }
步骤 4
创建过滤器链
FilterChain.java
import java.util.ArrayList; import java.util.List; public class FilterChain { private List<Filter> filters = new ArrayList<Filter>(); private Target target; public void addFilter(Filter filter){ filters.add(filter); } public void execute(String request){ for (Filter filter : filters) { filter.execute(request); } target.execute(request); } public void setTarget(Target target){ this.target = target; } }
步骤 5
创建过滤器管理器
FilterManager.java
public class FilterManager { FilterChain filterChain; public FilterManager(Target target){ filterChain = new FilterChain(); filterChain.setTarget(target); } public void setFilter(Filter filter){ filterChain.addFilter(filter); } public void filterRequest(String request){ filterChain.execute(request); } }
步骤 6
创建客户端
Client.java
public class Client { FilterManager filterManager; public void setFilterManager(FilterManager filterManager){ this.filterManager = filterManager; } public void sendRequest(String request){ filterManager.filterRequest(request); } }
步骤 7
使用客户端演示拦截过滤器设计模式。
FrontControllerPatternDemo.java
public class InterceptingFilterDemo { public static void main(String[] args) { FilterManager filterManager = new FilterManager(new Target()); filterManager.setFilter(new AuthenticationFilter()); filterManager.setFilter(new DebugFilter()); Client client = new Client(); client.setFilterManager(filterManager); client.sendRequest("HOME"); } }
步骤 8
验证输出。
Authenticating request: HOME request log: HOME Executing request: HOME
服务定位器模式
当我们想要使用 JNDI 查找定位各种服务时,可以使用服务定位器设计模式。考虑到查找 JNDI 服务的成本较高,服务定位器模式利用缓存技术。第一次需要服务时,服务定位器会在 JNDI 中查找并缓存服务对象。通过服务定位器进一步查找相同服务会在其缓存中进行,这在很大程度上提高了应用程序的性能。以下是这种设计模式的实体。
服务 - 将处理请求的实际服务。此类服务的引用需要在 JNDI 服务器中查找。
上下文/初始上下文 - JNDI 上下文,包含用于查找目的的服务引用。
服务定位器 - 服务定位器是通过 JNDI 查找获取服务的单点联系,它会缓存服务。
缓存 - 用于存储服务引用的缓存,以便重用它们。
客户端 - 客户端是通过 ServiceLocator 调用服务的对象。
实现
我们将创建ServiceLocator、InitialContext、Cache、Service作为代表我们实体的各种对象。Service1 和 Service2 代表具体的服务。
我们的演示类ServiceLocatorPatternDemo在这里充当客户端,并将使用ServiceLocator来演示服务定位器设计模式。
步骤 1
创建服务接口。
Service.java
public interface Service { public String getName(); public void execute(); }
步骤 2
创建具体的服务。
Service1.java
public class Service1 implements Service { public void execute(){ System.out.println("Executing Service1"); } @Override public String getName() { return "Service1"; } }
Service2.java
public class Service2 implements Service { public void execute(){ System.out.println("Executing Service2"); } @Override public String getName() { return "Service2"; } }
步骤 3
创建用于 JNDI 查找的 InitialContext。
InitialContext.java
public class InitialContext { public Object lookup(String jndiName){ if(jndiName.equalsIgnoreCase("SERVICE1")){ System.out.println("Looking up and creating a new Service1 object"); return new Service1(); }else if (jndiName.equalsIgnoreCase("SERVICE2")){ System.out.println("Looking up and creating a new Service2 object"); return new Service2(); } return null; } }
步骤 4
创建缓存。
Cache.java
import java.util.ArrayList; import java.util.List; public class Cache { private List<Service> services; public Cache(){ services = new ArrayList<Service>(); } public Service getService(String serviceName){ for (Service service : services) { if(service.getName().equalsIgnoreCase(serviceName)){ System.out.println("Returning cached "+serviceName+" object"); return service; } } return null; } public void addService(Service newService){ boolean exists = false; for (Service service : services) { if(service.getName().equalsIgnoreCase(newService.getName())){ exists = true; } } if(!exists){ services.add(newService); } } }
步骤 5
创建服务定位器。
ServiceLocator.java
public class ServiceLocator { private static Cache cache; static { cache = new Cache(); } public static Service getService(String jndiName){ Service service = cache.getService(jndiName); if(service != null){ return service; } InitialContext context = new InitialContext(); Service service1 = (Service)context.lookup(jndiName); cache.addService(service1); return service1; } }
步骤 6
使用ServiceLocator演示服务定位器设计模式。
ServiceLocatorPatternDemo.java
public class ServiceLocatorPatternDemo { public static void main(String[] args) { Service service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); } }
步骤 7
验证输出。
Looking up and creating a new Service1 object Executing Service1 Looking up and creating a new Service2 object Executing Service2 Returning cached Service1 object Executing Service1 Returning cached Service2 object Executing Service2
传输对象模式
当我们想要一次性地将具有多个属性的数据从客户端传递到服务器时,可以使用传输对象模式。传输对象也称为值对象。传输对象是一个简单的 POJO 类,具有 getter/setter 方法并且是可序列化的,以便它可以传输到网络上。它没有任何行为。服务器端业务类通常从数据库中获取数据并填充 POJO,然后将其发送到客户端或按值传递。对于客户端,传输对象是只读的。客户端可以创建它自己的传输对象并将其传递给服务器,以便一次性更新数据库中的值。以下是这种设计模式的实体。
业务对象 - 填充传输对象的业务服务。
传输对象 -简单的 POJO,只有设置/获取属性的方法。
客户端 - 客户端向业务对象请求或发送传输对象。
实现
我们将创建一个StudentBO作为业务对象,Student作为代表我们实体的传输对象。
我们的演示类TransferObjectPatternDemo在这里充当客户端,并将使用StudentBO和Student来演示传输对象设计模式。
步骤 1
创建传输对象。
StudentVO.java
public class StudentVO { private String name; private int rollNo; StudentVO(String name, int rollNo){ this.name = name; this.rollNo = rollNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getRollNo() { return rollNo; } public void setRollNo(int rollNo) { this.rollNo = rollNo; } }
步骤 2
创建业务对象。
StudentBO.java
import java.util.ArrayList; import java.util.List; public class StudentBO { //list is working as a database List<StudentVO> students; public StudentBO(){ students = new ArrayList<StudentVO>(); StudentVO student1 = new StudentVO("Robert",0); StudentVO student2 = new StudentVO("John",1); students.add(student1); students.add(student2); } public void deleteStudent(StudentVO student) { students.remove(student.getRollNo()); System.out.println("Student: Roll No " + student.getRollNo() +", deleted from database"); } //retrive list of students from the database public List<StudentVO> getAllStudents() { return students; } public StudentVO getStudent(int rollNo) { return students.get(rollNo); } public void updateStudent(StudentVO student) { students.get(student.getRollNo()).setName(student.getName()); System.out.println("Student: Roll No " + student.getRollNo() +", updated in the database"); } }
步骤 3
使用StudentBO演示传输对象设计模式。
TransferObjectPatternDemo.java
public class TransferObjectPatternDemo { public static void main(String[] args) { StudentBO studentBusinessObject = new StudentBO(); //print all students for (StudentVO student : studentBusinessObject.getAllStudents()) { System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); } //update student StudentVO student =studentBusinessObject.getAllStudents().get(0); student.setName("Michael"); studentBusinessObject.updateStudent(student); //get the student studentBusinessObject.getStudent(0); System.out.println("Student: [RollNo : " +student.getRollNo()+", Name : "+student.getName()+" ]"); } }
步骤 4
验证输出。
Student: [RollNo : 0, Name : Robert ] Student: [RollNo : 1, Name : John ] Student: Roll No 0, updated in the database Student: [RollNo : 0, Name : Michael ]