Design Pattern 简明教程
Design Pattern Quick Guide
设计模式代表了经验丰富的面向对象软件开发人员所使用的最佳实践。设计模式是软件开发人员在软件开发过程中面对的一般问题的解决方案。这些解决方案是由众多软件开发人员经过相当长一段时间通过反复试验获得的。
What is Gang of Four (GOF)?
1994 年,埃里希·伽马、理查德·海尔姆、拉尔夫·约翰逊和约翰·弗利斯德斯四位作者出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software 的书,这开启了软件开发中设计模式的概念。
这些作者被统称为 Gang of Four (GOF) 。根据这些作者,设计模式主要基于面向对象设计下列原则。
-
对接口编程,而不是实现
-
首选对象组合高于继承
Usage of Design Pattern
设计模式在软件开发中有两种主要用法。
Types of Design Pattern
根据设计模式参考手册 Design Patterns - Elements of Reusable Object-Oriented Software ,有 23 种设计模式。这些模式可以分类为三类:创建型模式、结构型模式和行为型模式。我们还将讨论另一类设计模式:J2EE 设计模式。
S.N. |
Pattern & Description |
1 |
Creational Patterns 这些设计模式提供了一种创建对象、同时隐藏创建逻辑的方法,而不是直接使用新操作符实例化对象。这为程序提供了更大的灵活性,以便决定为给定的用例创建哪些对象。 |
2 |
Structural Patterns 这些设计模式涉及类和对象组合。继承的概念用于组合接口并定义组合对象以获得新功能的方法。 |
3 |
Behavioral Patterns 这些设计模式专门关注对象之间的通信。 |
4 |
J2EE Patterns 这些设计模式专门关注表示层。Sun Java Center 识别出这些模式。 |
Factory Pattern
工厂模式是 Java 中使用最广泛的设计模式之一。这种设计模式属于创建模式,因为该模式提供了创建对象的最佳方法之一。
在工厂模式中,我们创建对象,而不向客户端公开创建逻辑,并使用通用接口引用新创建的对象。
Implementation
我们将创建 Shape 接口和实现 Shape 接口的具体类。作为下一步,将工厂类 ShapeFactory 定义为。
我们的演示类 FactoryPatternDemo 将使用 ShapeFactory 获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE/RECTANGLE/SQUARE)来获取它需要的对象类型。
Step 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.");
}
}
Step 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;
}
}
Step 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();
}
}
Design Pattern - Abstract Factory Pattern
抽象工厂模式围绕超级工厂进行,该超级工厂创建其他工厂。该工厂也称为工厂之工厂。这种设计模式属于创建模式,因为该模式提供了创建对象的最佳方法之一。
在抽象工厂模式中,一个接口负责创建工厂相关对象,而无需明确指定它们的类。每个生成的工厂都可以按照工厂模式提供对象。
Implementation
我们将创建一个形状接口和一个实现它的具体类。我们创建 AbstractFactory 抽象工厂类作为下一步。定义工厂类 ShapeFactory,它扩展了 AbstractFactory。创建了一个工厂创建器/生成器类 FactoryProducer。
AbstractFactoryPatternDemo,我们的演示类使用 FactoryProducer 获取 AbstractFactory 对象。它将信息(形状的 CIRCLE / RECTANGLE / SQUARE)传递给 AbstractFactory 以获取它需要的对象类型。
Step 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.");
}
}
Step 3
创建一个抽象类来获取普通和圆形形状对象的工厂。
AbstractFactory.java
public abstract class AbstractFactory {
abstract Shape getShape(String shapeType) ;
}
Step 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;
}
}
Step 5
创建一个工厂生成器/生产者类通过传递诸如形状的信息来获取工厂。
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(boolean rounded){
if(rounded){
return new RoundedShapeFactory();
}else{
return new ShapeFactory();
}
}
}
Step 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();
}
}
Singleton Pattern
单例模式是 Java 中最简单的设计模式之一。这种设计模式属于创建模式,因为此模式提供了创建对象的最佳方式之一。
此模式涉及一个负责创建自己对象的单个类,同时确保只创建一个对象。此类提供了一种访问其唯一对象的方法,该对象可以直接访问而无需实例化该类的对象。
Implementation
我们准备创建一个 SingleObject 类。SingleObject 类的构造函数为私有,并且有它自己的一个静态实例。
SingleObject 类提供一个静态方法来将它的静态实例提供给外部世界。SingletonPatternDemo,我们的演示类将使用 SingleObject 类来获取一个 SingleObject 对象。
Step 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!");
}
}
Step 2
获取 Singleton 类的唯一对象。
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();
}
}
Builder Pattern
建造者模式使用简单对象和逐步方法构建复杂对象。此类设计模式属于创建模式,该模式提供创建对象的最佳方法之一。
建造者类逐步构建最终对象。此建造者独立于其他对象。
Implementation
我们考虑了一家快餐店的商业案例,其典型餐点可能是一份汉堡和一杯冷饮。汉堡可以选择素食汉堡或鸡肉汉堡,并用包装纸包装。冷饮可以选择可乐或百事可乐,并装在瓶子里。
我们将创建一个 Item 接口,表示食品,如汉堡和冷饮,以及实现 Item 接口的具体类。还将创建一个 Packing 接口,表示食品包装,以及实现 Packing 接口的具体类。包装纸将用来包装汉堡,瓶子将用来包装冷饮。
然后,我们创建一个具有 Item 的 ArrayList 的 Meal 类和一个 MealBuilder,通过组合 Item 来构建不同类型的 Meal 对象。我们的演示类 BuilderPatternDemo 将使用 MealBuilder 来构建一个 Meal。
Step 1
创建一个表示食品和包装的 Item 接口。
Item.java
public interface Item {
public String name();
public Packing packing();
public float price();
}
Packing.java
public interface Packing {
public String pack();
}
Step 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";
}
}
Step 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();
}
Step 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";
}
}
Step 5
创建包含上述定义的 Item 对象的 Meal 类。
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());
}
}
}
Step 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;
}
}
Step 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());
}
}
Prototype Pattern
原型模式是指在考虑性能的情况下创建副本对象。此类设计模式属于创建模式,因为此模式提供了创建对象的最佳方式之一。
此模式涉及实现一个原型接口,该接口告诉克隆当前对象。当直接创建对象代价高昂时,将使用此模式。例如,在代价高昂的数据库操作之后要创建对象。我们可以缓存该对象,在下一次请求时返回其克隆,并在需要时及时更新数据库,从而减少对数据库的调用。
Implementation
我们将创建一个抽象类 Shape 和扩展 Shape 类的具体类。接下来定义一个 ShapeCache 类,它将 shape 对象存储在哈希表中,并在请求时返回它们的克隆。
我们的演示类 PrototypPatternDemo 将使用 ShapeCache 类获取 Shape 对象。
Step 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;
}
}
Step 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.");
}
}
Step 3
创建一个从数据库中获取具体对象并将它们存储在哈希表中的类。
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);
}
}
Step 4
PrototypePatternDemo 使用 ShapeCache 类从存储在哈希表中的形状中获取克隆。
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());
}
}
Adapter Pattern
适配器模式充当两个不兼容接口之间的桥梁。此类设计模式属于结构模式,因为此模式结合了两个独立接口的功能。
该模式包含一个负责加入独立或不兼容接口的功能的单一类。一个真实生活中的例子可能是充当存储卡和笔记本电脑之间的适配器的读卡器。你将存储卡插入读卡器,然后将读卡器插入笔记本电脑,以便可以通过笔记本电脑读取存储卡。
我们通过以下示例展示适配器模式的使用,其中音频播放器设备只能播放 mp3 文件,并且想使用能够播放 vlc 和 mp4 文件的高级音频播放器。
Implementation
我们有 MediaPlayer 接口和一个实现了 MediaPlayer 接口的具体类 AudioPlayer。AudioPlayer 默认可以播放 mp3 格式的音频文件。
我们有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的具体类。这些类可以播放 vlc 和 mp4 格式的文件。
我们希望 AudioPlayer 也可以播放其他格式。为了实现此目的,我们创建了一个实现了 MediaPlayer 接口并使用 AdvancedMediaPlayer 对象播放所需格式的适配器类 MediaAdapter。
AudioPlayer 使用适配器类 MediaAdapter,将其传递所需的音频类型,而不知道可以播放所需格式的实际类。我们的演示类 AdapterPatternDemo 将使用 AudioPlayer 类播放各种格式。
Step 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);
}
Step 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);
}
}
Step 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);
}
}
}
Step 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");
}
}
}
Step 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");
}
}
Bridge Pattern
桥用于我们需要将抽象与其实现分离的地方,以便两者可以独立变化。这种设计模式属于结构模式,因为此模式通过在实现类和抽象类之间提供一个桥结构来分离它们。
此模式涉及充当桥接器的接口,该接口使具体类的功能独立于界面实现者类。两种类型的类在不影响彼此的情况下可以在结构上进行更改。
我们通过以下示例演示如何使用桥接模式,其中可以使用相同的抽象类方法和不同的桥接实现者类以不同的颜色绘制圆。
Implementation
我们有一个充当桥式实现者和具体类 RedCircle、GreenCircle(实现 DrawAPI 接口)的 DrawAPI 接口。Shape 是一个抽象类,并会使用 DrawAPI 对象。我们的演示类 BridgePatternDemo 会使用 Shape 类绘制不同颜色的圆。
Step 1
创建桥接实现器接口。
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}
Step 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 +"]");
}
}
Step 3
使用 DrawAPI 接口创建抽象类 Shape。
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}
Step 4
使用 Gemini 实现 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);
}
}
Filter/Criteria Pattern
过滤模式或条件模式是一种设计模式,它允许开发人员使用不同的条件对一组对象进行过滤,并通过逻辑操作以解耦的方式对它们进行链接。这种类型的设计模式属于结构模式,因为该模式将多个条件组合在一起以获取单个条件。
Implementation
我们将创建 Person 对象、Criteria 接口和实现此接口的具体类,以便过滤 Person 对象列表。CriteriaPatternDemo 我们的演示类使用 Criteria 对象根据各种条件及其组合来过滤 Person 对象列表。
Step 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;
}
}
Step 2
创建 Criteria 接口。
Criteria.java
import java.util.List;
public interface Criteria {
public List<Person> meetCriteria(List<Person> persons);
}
Step 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;
}
}
Step4
使用不同的标准及其组合来筛选人员。
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()
+" ]");
}
}
}
Step 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
在我们需要将一组对象与单个对象类似地处理时,使用合成模式。合成模式按照树形结构组成对象以表示部分和整体层次结构。这类设计模式是结构模式,因为该模式创建组对象的树形结构。
此模式创建一个类,其中包含它自己的一组对象。该类提供了修改其相同对象组的方法。
我们正在使用以下示例演示合成模式的使用,展示组织的员工层次结构。
Implementation
我们有一个类 Employee,它充当合成模式的执行者类。我们的演示类 CompositePatternDemo 将使用 Employee 类添加部门级别层次结构并打印所有员工。
Step 1
创建具有员工对象列表的 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+" ]");
}
}
Step 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);
}
}
}
}
Step 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
装饰器模式允许添加新功能而不改变现有对象的结构。此类设计模式是结构模式,因为此模式充当现有类的包装器。
此模式创建一个装饰器类,它包装原始类并提供附加功能,保持类方法签名不变。
我们正在通过以下示例演示装饰器模式的使用,在该示例中我们将用某种颜色装饰一个形状而不更改形状类。
Implementation
我们将创建一个 Shape 接口以及实现 Shape 接口的具体类。然后我们创建了一个抽象装饰类 ShapeDecorator,它实现了 Shape 接口,并具有形状对象作为其实例变量。
RedShapeDecorator 是一个具体类,实现了 ShapeDecorator。
DecoratorPatternDemo 是我们的演示类,它将使用 RedShapeDecorator 装饰 Shape 对象。
Step 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");
}
}
Step 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();
}
}
Step 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");
}
}
Step 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();
}
}
Facade Pattern
外观模式隐藏了系统的复杂性,并为客户端提供了一个接口,客户端可以使用它来访问系统。这种设计模式属于结构模式,因为该模式会向现有系统添加一个接口来隐藏其复杂性。
此模式涉及一个提供客户端所需且委托调用现有的系统类方法的简化方法的类。
Implementation
我们将创建一个 Shape 接口和实现 Shape 接口的具体类。外观类 ShapeMaker 被定义为下一步。
ShapeMaker 类使用具体类委托用户的调用到这些类。FacadePatternDemo 是我们的演示类,它将使用 ShapeMaker 类来显示结果。
Step 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()");
}
}
Step 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();
}
}
Flyweight Pattern
享元模式主要用来减少创建的对象数,从而减少内存占用并提升性能。这种设计模式属于结构模式,因为此模式提供了减少对象计数的方法,从而提升了应用程序所需的结构对象。
享元模式尝试通过存储类似类型的现有对象并仅在找不到匹配对象时创建一个新对象来重用它们。我们将通过绘制 20 个位于不同位置的圆形来说明这个模式,但我们只创建一个对象。只有 5 种颜色可用,所以颜色属性被用来检查现有的 Circle 对象。
Implementation
我们将创建一个 Shape 接口和实现 Shape 接口的具体类 Circle。外观类 ShapeFactory 被定义为下一步。
ShapeFactory 具有 HashMap 的 Circle,其中密钥是 Circle 对象的颜色。每当请求来创建特定颜色的循环到 ShapeFactory 时。ShapeFactory 会检查其 HashMap 中的循环对象,如果找到 Circle 对象,则返回该对象,否则创建新对象,存储在 hashmap 中以备将来使用并返回给客户端。
FlyWeightPatternDemo,我们的演示类将使用 ShapeFactory 获得 Shape 对象。它将传递信息(红色/绿色/蓝色/黑色/白色)到 ShapeFactory 以获得所需颜色的圆。
Step 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);
}
}
Step 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;
}
}
Step 4
使用 Factory 根据颜色等信息来获得具体类对象。
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);
}
}
Step 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
在 Proxy 模式中,一个类表示另一个类的功能。这种设计模式属于结构模式。
在 Proxy 模式中,我们创建一个具有原始对象的对象,将其功能与外部世界进行接口。
Implementation
我们将创建一个 Image 接口和实现 Image 接口的具体类。ProxyImage 是一个代理类,用于减少 RealImage 对象加载的内存占用。
ProxyPatternDemo,我们的演示类将使用 ProxyImage 获得 Image 对象以根据需要加载和显示。
Step 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();
}
}
Step 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();
}
}
Chain of Responsibility Pattern
顾名思义,责任链模式为请求创建了一个接收器对象链。此模式基于请求类型将请求的发件人和接收者解耦。此模式属于行为模式。
在此模式中,每个接收器通常包含对另一个接收器的引用。如果一个对象无法处理请求,则将其传递给下一个接收器,依此类推。
Implementation
我们创建了一个具有日志记录级别的抽象类 AbstractLogger。然后我们创建了三种类型的记录器来扩展 AbstractLogger。每个记录器检查消息的级别到其级别并相应地打印,否则不打印并将其消息传递给下一个记录器。
Step 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);
}
Step 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);
}
}
Step 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.");
}
}
Step 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.
Command Pattern
命令模式是一种数据驱动设计模式,属于行为模式类别。请求被包装在对象中作为命令并传递到调用者对象。调用者对象查找可以处理此命令的适当对象,并把命令传递给相应的对象,该对象执行命令。
Implementation
我们创建了一个充当命令的接口 Order。我们创建了一个充当请求的 Stock 类。我们有具体的命令类 BuyStock 和 SellStock,实现了 Order 接口,将执行实际的命令处理。创建了一个充当调用者对象的类 Broker。它可以接受订单并下达订单。
Broker 对象使用命令模式根据命令类型识别哪个对象将执行哪个命令。我们的演示类 CommandPatternDemo 将使用 Broker 类演示命令模式。
Step 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");
}
}
Step 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();
}
}
Step 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();
}
}
Step 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();
}
}
Interpreter Pattern
解释器模式提供了一种评估语言语法或表达式的途径。这种模式属于行为模式。此模式涉及实现一个表达式接口,该接口讲述如何解释特定上下文。此模式用于 SQL 解析、符号处理引擎等。
Implementation
我们将创建一个接口 Expression,并创建实现 Expression 接口的具体类。定义了一个类 TerminalExpression,它充当问题上下文中主要的解释器。其他类 OrExpression、AndExpression 用于创建组合表达式。
我们的演示类 InterpreterPatternDemo 将使用 Expression 类创建规则并演示表达式的解析。
Step 1
创建一个表达式接口。
Expression.java
public interface Expression {
public boolean interpret(String context);
}
Step 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);
}
}
Step 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"));
}
}
Iterator Pattern
迭代器模式是 Java 和 .Net 编程环境中非常常见的设计模式。此模式用于获取一种方法,在无需了解其底层表示的情况下,以顺序方式访问集合对象的元素。
迭代器模式属于行为模式类别。
Implementation
我们将创建一个描述导航方法的 Iterator 接口,以及一个返回迭代器的 Container 接口。实现 Container 接口的具体类将负责实现 Iterator 接口并使用它
我们的演示类 IteratorPatternDemo 将使用 NamesRepository(一个具体类实现)来打印存储为 NamesRepository 中集合的名称。
Step 1
创建接口。
Iterator.java
public interface Iterator {
public boolean hasNext();
public Object next();
}
Container.java
public interface Container {
public Iterator getIterator();
}
Step 2
创建实现 Container 接口的具体类。此类具有实现 Iterator 接口的内部类 NameIterator。
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;
}
}
}
Step 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);
}
}
}
Mediator Pattern
调解器模式用于减少多个对象或类之间的通信复杂性。此模式提供一个调解器类,该类通常处理不同类之间的所有通信,并通过松散耦合支持代码的轻松维护。调解器模式属于行为模式类别。
Implementation
我们通过聊天室的示例来演示中介者模式,这里多个用户可以向聊天室发送消息,而聊天室负责向所有用户展示这些消息。我们创建了两个类 ChatRoom 和 User。User 对象将使用 ChatRoom 方法来共享其消息。
MediatorPatternDemo(我们的演示类)将使用 User 对象来展示它们之间的通信。
Step 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);
}
}
Step 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);
}
}
Memento Pattern
备忘录模式用于减少我们希望将对象的某个状态还原到某个先前状态的情况。备忘录模式属于行为模式范畴。
Implementation
备忘录模式使用三个执行者类。Memento 包含要还原对象的某个状态。Originator 在 Memento 对象中创建并存储状态,而 Caretaker 对象负责从 Memento 还原对象状态。我们创建了类 Memento、Originator 和 CareTaker。
MediatorPatternDemo(我们的演示类)将使用 CareTaker 和 Originator 对象来展示对象状态的还原。
Step 1
创建 Memento 类。
Memento.java
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
Step 2
创建 Originator 类
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();
}
}
Step 3
创建 CareTaker 类
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);
}
}
Step 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());
}
}
Observer Pattern
当对象之间存在一对多的关系(例如,如果修改一个对象,则其依赖对象将被自动通知)时,可以使用观察者模式。观察者模式属于行为模式类别。
Implementation
观察者模式使用三个参与者类。主题、观察者和客户。主题,用于附加和分离观察者到客户对象的方法的对象。我们创建了主题、观察者抽象类和扩展观察者抽象类的具体类。
ObserverPatternDemo,我们的演示类将使用主题和具体类对象来演示观察者模式的作用。
Step 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();
}
}
}
Step 2
创建观察者类。
Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
Step 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() );
}
}
Step 4
使用主题和具体观察者对象。
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);
}
}
State Pattern
在状态模式中,类行为会根据其状态而变化。这种设计模式属于行为模式。
在状态模式中,我们创建表示各种状态的对象,以及随着其状态对象的变化而行为发生变化的上下文对象。
Implementation
我们将创建一个定义动作的 State 接口以及实现 State 接口的具体状态类。Context 是一个承载状态的类。
StaePatternDemo,我们的演示类将使用 Context 和状态对象来演示根据状态类型而改变 Context 行为。
Step 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";
}
}
Step 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;
}
}
Step 4
使用 Context 查看状态改变时行为的变化。
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());
}
}
Null Object Pattern
在 Null 对象模式中,一个 null 对象替代了 NULL 对象实例的检查。Null 对象反映一种不采取任何操作的关系,而不是放置对 null 值的 if 检查。如果没有数据,也可以使用 Null 对象提供默认行为。
在 Null 对象模式中,我们创建一个指定要执行的各个操作的抽象类,扩展此类的具体类,以及提供此类的不执行实现的空对象类,并在需要检查 null 值时无缝地使用它。
Implementation
我们创建一个定义操作的抽象类 AbstractCustomer,此处为客户的姓名,以及扩展 AbstractCustomer 类的具体类。创建一个工厂类 CustomerFactory,基于传递给它的客户姓名返回 RealCustomer 或 NullCustomer 对象。
NullPatternDemo,我们的演示类,将使用 CustomerFactory 演示 Null 对象模式的使用。
Step 1
创建一个抽象类。
AbstractCustomer.java
public abstract class AbstractCustomer {
protected String name;
public abstract boolean isNil();
public abstract String getName();
}
Step 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;
}
}
Step 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();
}
}
Step 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());
}
}
Strategy Pattern
在策略模式中,一个类的行为或其算法可以在运行时更改。这种设计模式属于行为模式。
在策略模式中,我们创建代表各种策略的对象,以及随其策略对象而行为不同的上下文对象。策略对象更改上下文对象的可执行算法。
Implementation
我们将创建一个定义操作的策略接口和实现策略接口的具体策略类。Context 是使用策略的类。
StrategyPatternDemo,我们的演示类将使用 Context 和 strategy 对象来展示根据它部署或使用的策略,在 Context 行为中进行更改。
Step 1
创建一个接口。
Strategy.java
public interface Strategy {
public int doOperation(int num1, int num2);
}
Step 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;
}
}
Step 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);
}
}
Step 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));
}
}
Template Pattern
在 Template 中,一个抽象类公开了定义的执行其方法的方式/模板。其子类可以根据需要覆盖方法实现,但调用应该是按照抽象类定义的方式进行。此模式属于行为模式类别。
Implementation
我们将创建一个 Game 抽象类,它使用模板方法定义操作,将其设置为 final,以便不能将其覆盖。Cricket 和 Football 是具体类,扩展 Game 并覆盖其方法。
TemplatePatternDemo,我们的演示类将使用 Game 来展示模板模式用法。
Step 1
创建带有 final 模板方法的抽象类。
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();
}
}
Step 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!");
}
}
Visitor Pattern
在 Visitor 模式中,我们使用 visitor 类来更改 element 类的执行算法。这样,随着 visitor 的变化,element 的执行算法也会发生变化。此模式属于行为模式类别。按照此模式,element 对象必须接受 visitor 对象,以便 visitor 对象处理 element 对象上的操作。
Implementation
我们将创建一个 ComputerPart 接口,它定义 accept 操作。Keyboard、Mouse、Monitor 和 Computer 是实现 ComputerPart 接口的具体类。我们将定义另一个接口 ComputerPartVisitor,它将定义 visitor 类操作。Computer 使用具体 visitor 来执行相应的动作。
VisitorPatternDemo,我们的演示类将使用 Computer、ComputerPartVisitor 类来展示 visitor 模式用法。
Step 1
定义一个接口来表示元素。
ComputerPart.java
public interface class ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
Step 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);
}
}
Step 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);
}
Step 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.");
}
}
MVC Pattern
MVC 模式代表模型-视图-控制器模式。此模式用于分离应用程序的关注点。
-
Model - 模型表示一个携带数据的对象或 Java POJO。如果其数据更改,它也可以具有更新控制器的逻辑。
-
View - 视图表示模型中包含的数据的可视化。
-
Controller - 控制器对模型和视图均有效。它控制数据流到模型对象,并在数据更改时更新视图。它使视图和模型保持分离。
Implementation
我们将创建一个充当模型的学生对象。StudentView 将是一个可以将学生详细信息打印到控制台的视图类,而 StudentController 是负责将数据存储在 Student 对象中并相应地更新视图 StudentView 的控制器类。
MVCPatternDemo,我们的演示类,将使用 StudentController 来演示 MVC 模式的用法。
Step 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;
}
}
Step 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);
}
}
Step 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());
}
}
Step 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;
}
}
Business Delegate Pattern
业务委托模式用于分离表示层和业务层。主要用于减少表示层代码中与业务层代码进行通信或远程查找功能。我们在业务层中具有下列实体。
-
Client - 表示层代码可能是 JSP、servlet 或 UI Java 代码。
-
Business Delegate - 客户端实体的一个单一入口点类,用于提供对业务服务方法的访问。
-
LookUp Service - 查找服务对象负责获取相关的业务实现,并向业务委托对象提供对业务对象的访问。
-
Business Service - 业务服务界面。具体类实现此业务服务以提供实际的业务实现逻辑。
Implementation
我们将创建一个 Client、BusinessDelegate、BusinessService、LookUpService、JMSService 和 EJBService,它们表示业务委托模式的各个实体。
我们的演示类 BusinessDelegatePatternDemo 将使用 BusinessDelegate 和 Client 来演示业务委托模式的使用。
Step 1
创建 BusinessService 界面。
BusinessService.java
public interface BusinessService {
public void doProcessing();
}
Step 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");
}
}
Step 3
创建业务查找服务。
BusinessLookUp.java
public class BusinessLookUp {
public BusinessService getBusinessService(String serviceType){
if(serviceType.equalsIgnoreCase("EJB")){
return new EJBService();
}else {
return new JMSService();
}
}
}
Step 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();
}
}
Step 5
创建客户端。
Student.java
public class Client {
BusinessDelegate businessService;
public Client(BusinessDelegate businessService){
this.businessService = businessService;
}
public void doTask(){
businessService.doTask();
}
}
Step 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();
}
}
Composite Entity Pattern
复合实体模式用于 EJB 持久性机制。复合实体是一个 EJB 实体 Bean,它表示一个对象图。当更新复合实体时,由 EJB 实体 Bean 管理的内部相关对象 Bean 会自动得到更新。下面是复合实体 Bean 中的参与者。
-
Composite Entity - 它是主要实体 Bean。它可以是粗粒度的,也可以包含一个粗粒度的对象,以用于持久性目的。
-
Coarse-Grained Object - 这个对象包含相关对象。它有自己的生命周期,还管理相关对象的生命周期。
-
Dependent Object - 相关对象是一个对象,它的持久性生命周期依赖于粗粒度对象。
-
Strategies - 策略表示如何实现复合实体。
Implementation
我们将创建充当 CompositeEntity 的 CompositeEntity 对象。CoarseGrainedObject 将是一个包含相关对象的类。我们的演示类 CompositeEntityPatternDemo 将使用 Client 类演示复合实体模式的使用。
Step 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;
}
}
Step 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()};
}
}
Step 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();
}
}
Step 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);
}
}
Step 5
使用 Client 来演示 Composite Entity 设计模式用法。
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();
}
}
Data Access Object Pattern
数据访问对象模式或 DAO 模式用于将低级别数据访问 API 或操作从高级业务服务中分离。以下是数据访问对象模式中的参与者。
-
Data Access Object Interface - 此接口定义要在模型对象上执行的标准操作。
-
Data Access Object concrete class - 此类实现上述接口。此类负责从数据源获取数据,该数据源可以是数据库/xml 或任何其他存储机制。
-
Model Object or Value Object - 此对象是包含 get/set 方法的简单 POJO,用于存储使用 DAO 类检索的数据。
Implementation
我们将创建一个充当模型或值对象的 Student 对象。StudentDao 是数据访问对象接口。StudentDaoImpl 是实现数据访问对象接口的具体类。我们的演示类 DaoPatternDemo 将使用 StudentDao 演示数据访问对象模式的使用。
Step 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;
}
}
Step 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);
}
Step 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");
}
}
Step 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()+" ]");
}
}
Front Controller Pattern
前端控制器设计模式用于提供集中式请求处理机制,以便所有请求都由单个处理程序处理。此处理程序可以执行身份验证/授权/请求日志记录或跟踪,然后将请求传递到相应的处理程序。以下是这种设计模式的实体。
-
Front Controller - 处理发送到应用程序(基于 Web 或基于桌面的)的各种请求的单一处理程序。
-
Dispatcher - 前端控制器可以使用分派器对象,该对象可以将请求分派到相应的特定处理程序。
-
View - 视图是针对其发出请求的对象。
Implementation
我们将创建一个 FrontController、Dispatcher,它们分别充当前端控制器和分发器。HomeView 和 StudentView 表示前端控制器可以接收请求的各种视图。
我们的演示类 FrontControllerPatternDemo 将使用 FrontController 来演示前端控制器设计模式。
Step 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");
}
}
Step 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();
}
}
}
Step 3
创建前端控制器
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);
}
}
}
Intercepting Filter Pattern
当我们希望对请求或应用程序的响应进行一些预处理/后处理时,将使用拦截过滤器设计模式。在将请求传递给实际目标应用程序之前,对请求定义并应用过滤器。过滤器可以对请求进行身份验证/授权/记录或跟踪,然后将请求传递给相应的处理程序。以下是此类设计模式的实体。
-
Filter - 请求处理程序执行请求之前或之后执行特定任务的过滤器。
-
Filter Chain - 过滤器链携带有不同的过滤器,并帮助按照目标上的定义顺序执行这些过滤器。
-
Target - 目标对象是请求处理程序
-
Filter Manager - 过滤器管理程序管理过滤器和过滤器链。
-
Client - 客户端是向目标对象发送请求的对象。
Implementation
我们将创建一个过滤器链、过滤器管理程序、目标和客户端作为代表实体的不同对象。AuthenticationFilter 和 DebugFilter 表示具体过滤器。
InterceptingFilterDemo 我们的演示类将使用客户端演示拦截过滤器设计模式。
Step 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);
}
}
Step 3
创建目标
Target.java
public class Target {
public void execute(String request){
System.out.println("Executing request: " + request);
}
}
Step 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;
}
}
Step 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);
}
}
Step 6
创建客户端
Client.java
public class Client {
FilterManager filterManager;
public void setFilterManager(FilterManager filterManager){
this.filterManager = filterManager;
}
public void sendRequest(String request){
filterManager.filterRequest(request);
}
}
Step 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");
}
}
Service Locator Pattern
在使用 JNDI 查找定位各种服务时,使用服务定位器设计模式。考虑到为服务查找 JNDI 的高成本,Service Locator 模式利用缓存技术。第一次需要服务时,Service Locator 会在 JNDI 中查找并缓存服务对象。通过 Service Locator 进一步查找或相同的服务在其缓存中进行,极大地提高了应用程序的性能。以下是这种设计模式的实体。
-
Service - 处理请求的实际服务。此类服务的引用要在 JNDI 服务器中查找。
-
Context / Initial Context - JNDI 上下文,携带用于查找目的的服务的引用。
-
Service Locator - 服务定位器是通过 JNDI 查找获取服务的单一接触点,并缓存服务。
-
Cache - 存储服务引用的缓存,以重用它们
-
Client - 客户端是通过 ServiceLocator 调用服务的对象。
Implementation
我们将创建一个 ServiceLocator、InitialContext、Cache、Service 作为表示我们实体的各种对象。Service1 和 Service2 表示具体服务。
ServiceLocatorPatternDemo,我们的演示类在此充当客户端,并将使用 ServiceLocator 演示服务定位器设计模式。
Step 1
创建服务接口。
Service.java
public interface Service {
public String getName();
public void execute();
}
Step 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";
}
}
Step 3
为 JNDI 查找创建初始上下文
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;
}
}
Step 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);
}
}
}
Step 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;
}
}
Step 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();
}
}
Transfer Object Pattern
传输对象模式用于希望一次性从客户端向服务器传递具有多个属性的数据时。传输对象也称为值对象。传输对象是一个简单的 POJO 类,它拥有 getter/setter 方法,并且可以序列化,以便通过网络进行传输。它没有任何行为。服务器端业务类通常从数据库获取数据并填充 POJO,然后将其发送到客户端或按值传递。对于客户端而言,传输对象是只读的。客户端可以创建自己的传输对象并将其传递给服务器,以便一次性更新数据库中的值。以下是该类型设计模式的实体。
-
Business Object - 填充传输对象数据的业务服务。
-
Transfer Object - 简单 POJO,仅具有用于设置/获取属性的方法。
-
Client - 客户端向业务对象请求或发送传输对象。
Implementation
我们将创建 StudentBO 作为业务对象,创建 Student 作为传输对象来表示我们的实体。
TransferObjectPatternDemo,我们的演示类在这里充当客户端,并将使用 StudentBO 和 Student 来演示传输对象设计模式。
Step 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;
}
}
Step 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");
}
}
Step 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()+" ]");
}
}