为了方便巩固所学的设计模式,决定以边写总结边学习的方式加深理解。
设计模式就是众多的软件开发前人总结出来的代码设计经验,为了让代码重用性更高,更易于理解和扩展。
一、单例模式
首先从简单的开始,最先接触的是单例模式,属于创建型模式,它由自己创建自己的实例,并且只能有一个,所有其他对象获取到该类的实例都是同一个,保证该类的实例只被创建了一次。
比如一个人只有一个父亲,他的baby叫爸爸只有他一个,不会因为叫的次数多而改变,永远只有父亲这一个实例
代码示例:
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
public class SingletonPatternDemo {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
//获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
二、工厂模式
工厂模式就是将类的实例化延迟到子类中,按需求实例化。
比如现在有一个汉堡店,店里有鸡腿汉堡、牛肉堡等,去店里报个名字别人就知道要做哪种汉堡。只将这一个汉堡类实例化而不实例化所有汉堡类。这就是工厂模式的原理,缺点就是一个工厂只能有一个种类的商品。汉堡店就只有汉堡,如果要增加冷饮等其他的只能再新建一个冷饮店(工厂类)。
代码示例:
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("SQUARE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
}
}
三、抽象工厂模式
工厂模式略显单调,只是单一生产某一种商品,抽象工厂模式就稍微延申的一点点,为多种商品提供工厂。上面的工厂模式可以看到,几个类实现一个接口,想用哪个就实例化哪一个,抽象工厂模式就稍有不同,它在实现接口的类后工厂类前添加了一个抽象类,由这个抽象类控制工厂类生产哪些商品,这样就能使代码的扩展性变高。如果现在汉堡店里不只卖汉堡,还想卖冷饮、披萨,只需增加一个接口,再让抽象类实现这个新的接口对应的方法。
代码示例:
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
public interface Color {
void fill();
}
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
public class Blue implements Color {
@Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
public abstract class AbstractFactory {
public abstract Color getColor(String color);
public abstract Shape getShape(String shape) ;
}
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
public Color getColor(String color) {
return null;
}
}
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
public 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;
}
}
判断创建哪一个工厂
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;
}
}
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//获取形状工厂
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//获取形状为 Circle 的对象
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取形状为 Rectangle 的对象
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取形状为 Square 的对象
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
//获取颜色工厂
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
//获取颜色为 Red 的对象
Color color1 = colorFactory.getColor("RED");
//调用 Red 的 fill 方法
color1.fill();
//获取颜色为 Green 的对象
Color color2 = colorFactory.getColor("Green");
//调用 Green 的 fill 方法
color2.fill();
//获取颜色为 Blue 的对象
Color color3 = colorFactory.getColor("BLUE");
//调用 Blue 的 fill 方法
color3.fill();
}
}
四、建造者模式
建造者模式也是创建型模式,不同于工厂模式的针对性创造,一种工厂生产一种商品。我们上面举的例子是汉堡店根据需求做哪种汉堡,或者冷饮。建造者模式就类似在店里点单,这个点单是任意的,不管汉堡还是冷饮都可以随意搭配点。下面看代码理解
代码示例:
这是一个食物条目接口
public interface Item {
public String name();//名字
public Packing packing();//包装
public float price(); //价格
}
包装接口
public interface Packing {
public String pack();
}
实现包装接口的类
public class Wrapper implements Packing {
@Override
public String pack() {
return "Wrapper";
}
}
public class Bottle implements Packing {
@Override
public String pack() {
return "Bottle";
}
}
实现食物接口(这里抽象方法为什么不实现接口中的name()方法,百思不得其解,还在查找资料)
public abstract class Burger implements Item {
@Override
public Packing packing() {
return new Wrapper();
}
@Override
public abstract float price();
}
public abstract class ColdDrink implements Item {
@Override
public Packing packing() {
return new Bottle();
}
@Override
public abstract float price();
}
public class VegBurger extends Burger {
@Override
public float price() {
return 25.0f;
}
@Override
public String name() {
return "Veg Burger";
}
}
public class ChickenBurger extends Burger {
@Override
public float price() {
return 50.5f;
}
@Override
public String name() {
return "Chicken Burger";
}
}
public class Coke extends ColdDrink {
@Override
public float price() {
return 30.0f;
}
@Override
public String name() {
return "Coke";
}
}
public class Pepsi extends ColdDrink {
@Override
public float price() {
return 35.0f;
}
@Override
public String name() {
return "Pepsi";
}
}
import java.util.ArrayList;
import java.util.List;
public class Meal {
//定义为私有,不允许外部使用List,只能通过内部封装好的方法使用List
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());
}
}
}
这里就是一个点单的过程,把想添加的食物添加到集合中
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;
}
}
输出点单信息
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());
}
}
五、原型模式
用于创建重复对象,同时又能保证性能,在创建一个对象代价较大时可以采用这种模式,这种模式可以克隆对象,通俗的说就是可以复制一个对象。这个模式空口白话有点难以理解还是边看代码边理解。
创建一个类实现Cloneable接口,重写其中的clone方法,这一步操作就是克隆
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;
}
}
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square extends Shape {
public Square(){
type = "Square";
}
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
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();
}
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
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);
}
}
输出的是克隆对象
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());
}
}
这个是我目前学习耗时最多的一个,为了方便克隆的理解我还找了另一段代码
实现接口Cloneable不重写clone方法直接调用clone方法所克隆的对象在原对象改变时也会跟着改变,即浅复制;写clone方法后,克隆对象不会跟着原对象变化,即深复制
public class CloneTest implements Cloneable{
private byte[] a = {1, 2, 3, 4};
private byte[] b = {5, 6, 7, 8};
public CloneTest clone() {
CloneTest copy = null;
try {
copy = (CloneTest) super.clone();
copy.a = this.a.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return copy;
}
public byte[] getA() {
return this.a;
}
public byte[] getB() {
return this.b;
}
public static void main(String[] args) {
CloneTest original = new CloneTest();
CloneTest cloned = original.clone();
System.out.println("original.a == cloned.a : " + (original.getA() == cloned.getA()));
System.out.println("cloned.a[3] = " + cloned.getA()[3]);
original.getA()[3] = 9;
System.out.println("cloned.a[3] = " + cloned.getA()[3]);
System.out.println("original.b == cloned.b : " + (original.getB() == cloned.getB()));
System.out.println("cloned.b[3] = " + cloned.getB()[3]);
original.b[3] = 10;
System.out.println("cloned.b[3] = " + cloned.getB()[3]);
}
}
输出结果
original.a == cloned.a : false
cloned.a[3] = 4
cloned.a[3] = 4
original.b == cloned.b : true
cloned.b[3] = 8
cloned.b[3] = 10
待续。。。。