设计模式代表有经验的面向对象软件开发人员使用的最佳实践。 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。 这些解决方案是由许多软件开发人员在相当长的时间内通过试错获得的。
设计模式四人帮(GOF)是什么?
1994年,有四位作者:Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides发表了一本题为《设计模式 - 可重用的面向对象软件元素》的图书,该书在软件开发中开创了设计模式的概念。
这些作者被统称为四人帮(GOF)。 根据这些作者,设计模式主要基于以下面向对象设计的原则:
- 程序到一个接口不用实现。
- 有利于对继承对象组合。
设计模式的使用
设计模式在软件开发中有两个主要用途。
开发人员的通用平台
设计模式提供了标准术语,并且特定于应用折场景。 例如,单例设计模式表示使用单个对象,所以熟悉单一设计模式的所有开发人员都将使用单个对象,并且他们可以告诉对方程序正在遵循单例模式。
最佳实践
设计模式已经经过一段很长的时间发展,它们为软件开发过程中面临的某些问题提供了最佳解决方案。 学习这些模式有助于无经验的开发人员以一种简单快捷的方式学习软件设计。
设计模式的类型
根据设计模式参考《设计模式 - 可重用的面向对象软件元素》一书中所述,一共有23
种设计模式可以分为三类:创造模式,结构模式和行为模式。在这里我们还将讨论另一类设计模式:J2EE设计模式。
编号 | 模式和说明 |
---|---|
1 | 创造模式 -这些设计模式提供了一种创建对象而隐藏创建逻辑的方法,而不是直接使用 new 操作符来实例化对象。 这使程序在决定对于给定的用例需要创建哪些对象时具有更大的灵活性。 |
2 | 结构模式 - 这些设计模式涉及类和对象组成。 继承概念用于组成接口并定义方法组合对象以获得新功能。 |
3 | 行为模式 - 这些设计模式是特别侧重于对象之间的通信。 |
4 | J2EE模式 - 这些设计模式特别涉及表示层。 这些模式由Sun Java Center 标识。 |
另外,设计模式是与编程语言无关的,它是用于解决常见的面向对象的设计问题。
设计模式代表一个想法,而不是一个实现。
通过使用设计模式,可以使我们的代码更灵活,可重用和可维护。
Java本身内部遵循设计模式。
在核心java中,主要有三种类型的设计模式,它们可进一步分为以下子部分:
1. 创造设计模式
工厂模式
抽象工厂模式
单例模式
原型模式
Builder模式
2.结构设计模式
适配器(Adapter)模式
桥接(Bridge)模式
组合模式
装饰者(Decorator)模式
外观(Facade)模式
享元(Flyweight)模式
代理(Proxy)模式
3.行为设计模式
责任链模式
命令模式
解释器模式
迭代器模式
调解者(Mediator)模式
备忘录模式
观察者模式
状态模式
策略模式
模板模式
访问者模式
工厂设计模式
工厂模式是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 circle shape3.draw(); } }
第5步
验证输出结果如下-
Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.
抽象工厂模式
抽象工厂模式是一个超级工厂,用来创建其他工厂。 这个工厂也被称为工厂的工厂。 这种类型的设计模式属于创建模式,因为此模式提供了创建对象的最佳方法之一。
在抽象工厂模式中,接口负责创建相关对象的工厂,而不明确指定它们的类。 每个生成的工厂可以按照工厂模式提供对象。
实现实例
我们将创建一个Shape
和Color
接口并实现这些接口的具体类。在下一步中,将创建一个抽象工厂类AbstractFactory
。在每个工厂类ShapeFactory
和ColorFactory
定义都是扩展自AbstractFactory
。创建工厂创建者/生成器类 - FactoryProducer
。
AbstractFactoryPatternDemo
这是一个演示类,使用FactoryProducer
来获取AbstractFactory
对象。 它会将信息(CIRCLE
/ RECTANGLE
/ SQUARE
)传递给AbstractFactory
以获取所需的对象类型。 它还将信息(用于Color
的 RED
/ GREEN
/ BLUE
)传递给AbstractFactory
以获取所需的对象类型。
第1步
创建Shape
的接口。
Shape.java
public interface Shape {
void draw();
}
Java
第2步
创建实现相同接口的具体类。
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Java
Square.java
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Java
Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
Java
第3步
创建一个Colors
接口,如下所示
Color.java
public interface Color {
void fill();
}
Java
第4步
创建实现相同接口的具体类。
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
Java
Green.java
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
Java
Blue.java
public class Blue implements Color {
@Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
Java
第5步
创建实现相同接口的具体类。
AbstractFactory.java
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
Java
第6步
创建实现相同接口的具体类。
创建工厂类,根据给定信息扩展AbstractFactory
以生成具体类的对象。
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
@Override
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;
}
@Override
Color getColor(String color) {
return null;
}
}
Java
ColorFactory.java
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
}else if(color.equalsIgnoreCase("GREEN")){
return new Green();
}else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
Java
第7步
创建工厂生成器/生产器类,通过传递如Shape
或Color
等信息来获取工厂
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
}else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
Java
第8步
使用FactoryProducer
来获取AbstractFactory
,以便通过传递类型等信息来获取具体类的工厂。
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//get an object of Shape Circle
Shape shape1 = shapeFactory.getShape("CIRCLE");
//call draw method of Shape Circle
shape1.draw();
//get an object of Shape Rectangle
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape2.draw();
//get an object of Shape Square
Shape shape3 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape3.draw();
//get color factory
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
//get an object of Color Red
Color color1 = colorFactory.getColor("RED");
//call fill method of Red
color1.fill();
//get an object of Color Green
Color color2 = colorFactory.getColor("Green");
//call fill method of Green
color2.fill();
//get an object of Color Blue
Color color3 = colorFactory.getColor("BLUE");
//call fill method of Color Blue
color3.fill();
}
}
Java
第9步
验证输出,结果如下 -
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
单例模式
单例(Singleton)模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建模式,因为此模式提供了创建对象的最佳方法之一。
这种模式涉及一个类,它负责创建一个对象,同时确保只创建一个对象。这个类提供了一种方法来访问它的唯一对象,可以直接访问,而不需要实例化类的对象。
实现实例
我们将创建一个单一对象类 - SingleObject
。单个对象(SingleObject
)类的构造函数是私有的,并且具有自身的静态实例。
SingleObject
类提供了一个静态方法来获取其静态实例到外部世界。SingletonPatternDemo
或示例类将使用SingleObject
类来获取SingleObject
对象。
第1步
创建一个Singleton类,
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!");
}
}
Java
第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();
}
}
Java
第3步
验证输出,得到结果如下 -
Hello World!
建造者(Builder)模式
构建器(Builder)模式使用简单对象并使用逐步方法构建复杂对象。 这种类型的设计模式属于创建模式,因为此模式提供了创建对象的最佳方法之一。
构建器(Builder)模式构建器逐步构建最终对象,此构建器独立于其他对象。
实例实例
我们考虑了一家快餐店的商业案例,其中典型的餐点可能是汉堡和冷饮。 汉堡可以是一个素食汉堡或鸡肉汉堡,将被包装进行包装。 冷饮可以是一个可乐或百事将装放在一个瓶子中。
我们将创建一个Item
接口,表示食品项目,如汉堡包和冷饮料以及实现Item
接口的具体类。还有一个包装接口,表示食品包装和实现包装接口的具体类,因为汉堡包装在包装和冷饮将包装成瓶子。
然后创建一个具有ItemListList
和MealBuilder
的Meal
类,通过组合Item
来构建不同类型的Meal
对象。 BuilderPatternDemo
这是一个演示类将使用MealBuilder
构建一个食品套餐。
第1步
创建两个接口分别代表食品和包装的项目(Item
和 Packing
),如下所示 -
Item.java
public interface Item {
public String name();
public Packing packing();
public float price();
}
Java
Packing.java
public interface Packing {
public String pack();
}
Java
第2步
创建实现Packing
接口的具体类。如下代码所示 -
Wrapper.java
public class Wrapper implements Packing {
@Override
public String pack() {
return "Wrapper";
}
}
Java
Bottle.java
public class Bottle implements Packing {
@Override
public String pack() {
return "Bottle";
}
}
Java
第3步
创建抽象类实现Item
接口提供默认功能。
Burger.java
public abstract class Burger implements Item {
@Override
public Packing packing() {
return new Wrapper();
}
@Override
public abstract float price();
}
Java
ColdDrink.java
public abstract class ColdDrink implements Item {
@Override
public Packing packing() {
return new Bottle();
}
@Override
public abstract float price();
}
Java
第4步
创建扩展汉堡(Burger
)和冷饮(ColdDrink
)类的具体类
VegBurger.java
public class VegBurger extends Burger {
@Override
public float price() {
return 25.0f;
}
@Override
public String name() {
return "Veg Burger";
}
}
Java
ChickenBurger.java
public class ChickenBurger extends Burger {
@Override
public float price() {
return 50.5f;
}
@Override
public String name() {
return "Chicken Burger";
}
}
Java
Coke.java
public class Coke extends ColdDrink {
@Override
public float price() {
return 30.0f;
}
@Override
public String name() {
return "Coke";
}
}
Java
Pepsi.java
public class Pepsi extends ColdDrink {
@Override
public float price() {
return 35.0f;
}
@Override
public String name() {
return "Pepsi";
}
}
Java
第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());
}
}
}
Java
第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;
}
}
Java
第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());
}
}
Java
第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
中存储形状(Shape
)对象,并在请求时返回其克隆。
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;
}
}
Java
第2步
创建扩展上述类的具体类。
Rectangle.java
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Java
Square.java
public class Square extends Shape {
public Square(){
type = "Square";
}
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Java
Circle.java
public class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
Java
第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);
}
}
Java
第4步
PrototypePatternDemo
使用ShapeCache
类来获取存储在Hashtable
中的形状(shape
)的克隆。
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());
}
}
Java
第5步
验证输出,执行上面的代码得到以下结果 -
Shape : Circle
Shape : Square
Shape : Rectangle