设计模式-创建型模式

1、工厂模式

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

通俗的讲,工厂模型的本质就是用工厂方法代替new操作创建一种实例化对象的方式,以提供一种方便地创建有同种类型接口的产品的复杂对象。

以创建手机为例:

(1)定义接口:

public interface Phone {
    String brand();
}

(2)定义实现类:

public class Iphone implements Phone {
    @Override
    public String brand() {
        return "this is a Apple phone";
    }
}

public class HuaWei implements Phone {
    @Override
    public String brand() {
        return "this is a Huawei phone";
    }
}

(3)定义工厂类:

public class factory_model {
    public Phone createPhone (String phoneName){
        if("Apple".equals(phoneName)){
            return new Iphone();
        }else if("HuaWei".equals(phoneName)){
            return new HuaWei();
        }else {
            return null;
        }
    }
}

(4)使用工厂模式:

public class Main {
    public static void main(String[] args) {
        factory_model factory = new factory_model();
        Phone huawei = factory.createPhone("HuaWei");
        Phone apple = factory.createPhone("Apple");
        System.out.println(huawei.brand());
        System.out.println(apple.brand());
    }
}

2、抽象工厂模式

抽象工厂模式在工厂模式上添加了一个创建不同工厂的抽象接口,该接口可叫做超级工厂。

在使用过程中,我们首先通过抽象接口创建出不同的工厂对象,然后根据不同的工厂对象创建不同的对象。

以不同品牌工厂生产手机和电脑为例:

(1)手机类产品的接口定义:

public interface Phone {
    String call();
}

(2)手机类产品的实现类定义:

public class PhoneApple implements Phone {
    @Override
    public String call() {
        return " call somebody by apple phone";
    }
}

public class PhoneHuaWei implements Phone {
    @Override
    public String call() {
        return " call somebody by huawei phone";
    }
}

(3)电脑类产品的接口定义:

public interface Computer {
    String internet();
}

(4)电脑类产品的实现类定义:

public class ComputerApple implements Computer {
    @Override
    public String internet() {
        return "surf the internet by apple computer";
    }
}

public class ComputerHuaWei implements Computer {
    @Override
    public String internet() {
        return "surf the internet by huawei computer";
    }
}

(5)抽象工厂定义:

public abstract class AbstractFactory {
    public abstract Phone createPhone(String brand);
    public abstract Computer createComputer(String brand);
}

(6)手机工厂类的定义:

public class PhoneFactory extends AbstractFactory {

    @Override
    public Phone createPhone(String brand) {
        if("Apple".equals(brand)){
            return new PhoneApple();
        }else if("HuaWei".equals(brand)){
            return new PhoneHuaWei();
        }else {
            return null;
        }
    }

    @Override
    public Computer createComputer(String brand) {
        return null;
    }
}

(7)电脑工厂类的定义:

public class ComputerFactory extends AbstractFactory {

    @Override
    public Phone createPhone(String brand) {
        return null;
    }

    @Override
    public Computer createComputer(String brand) {

        if("Apple".equals(brand)){
            return new ComputerApple();
        }else if("HuaWei".equals(brand)){
            return new ComputerHuaWei();
        }else {
            return null;
        }
    }
}

(8)使用抽象工厂:

public class Main {
    public static void main(String[] args) {
        AbstractFactory phoneFactory = new PhoneFactory();
        Phone phoneApple = phoneFactory.createPhone("Apple");
        Phone phoneHuaWei = phoneFactory.createPhone("HuaWei");
        System.out.println(phoneApple.call());
        System.out.println(phoneHuaWei.call());

        AbstractFactory computerFactory = new ComputerFactory();
        Computer computerApple = computerFactory.createComputer("Apple");
        Computer computerHuaWei = computerFactory.createComputer("HuaWei");
        System.out.println(computerApple.internet());
        System.out.println(computerHuaWei.internet());
    }
}

3、单例模式

单例模式是保证系统实例唯一性的重要手段。

单例模式首先通过将类的实例化方法私有化来防止程序通过其他方式创建该类实例,然后通过提供一个全局唯一获取该类实例的方法帮助用户获取类的实例,用户只能通过调用该方法获取类的实例。

单例模式的常见写法:懒汉式(线程安全)、饿汉式、静态内部类和双重校验锁。

(1)懒汉式(线程安全)

这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低。

public class LazySingelton {
    private static LazySingelton instance;
    public LazySingelton() {}
    public static synchronized LazySingelton getInstance() {
        if (instance == null) {
            instance = new LazySingelton();
        }
        return instance;
    }
}

(2)饿汉式

这种方式比较常用,但容易产生垃圾对象。

public class HungrySingleton {
    private static HungrySingleton instance = new HungrySingleton();
    private HungrySingleton(){};
    public static HungrySingleton getInstance(){
        return instance;
    }
}

(3)静态内部类

静态内部类通过在类中定义一个静态内部类,将对象实例的定义和初始化放在内部类完成,在获取对象时通过静态内部类调用其单例对象。

public class Singleton {
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }
    public Singleton() {}
    public static final Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

(4)双重校验锁

双重校验锁模式是指在懒汉式的基础上做进一步优化,给静态对象的定义加上volatile锁来保证初始化时对象的唯一性,在获取对象时通过synchronized给单例类加锁来保证操作唯一性。

这种方式安全且在多线程情况下能保持高性能。

public class Lock2Singleton {
    private volatile static Lock2Singleton singleton;
    private Lock2Singleton(){}
    public static Lock2Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Lock2Singleton();
                }
            }
        }
        return singleton;
    }
}

4、建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象,用于将一个复杂的构建与其表示分离,使得同样的构建过程可以创建不同的表示,然后通过一个Builder类创建最终的对象。

假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。

(1)创建一个表示食物条目和食物包装的接口。

public interface Item {
    public String name();
    public Packing packing();
    public float price();
}

public interface Packing {
    public String pack();
}

(2)创建实现 Packing 接口的实体类。

public class Bottle implements Packing {
    @Override
    public String pack() {
        return "Bottle";
    }
}

public class Wrapper implements Packing {
    @Override
    public String pack() {
        return "Wrapper";
    }
}

(3)创建实现 Item 接口的抽象类,该类提供了默认的功能。

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();
}

(4)创建扩展了 Burger 和 ColdDrink 的实体类。

public class ChickBurger extends Burger {
    @Override
    public float price() {
        return 50.5f;
    }

    @Override
    public String name() {
        return "Chicken Burger";
    }
}

public class VegBurger extends Burger {

    @Override
    public float price() {
        return 25.0f;
    }

    @Override
    public String name() {
        return "Veg 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";
    }
}

(5)创建一个 Meal 类,带有上面定义的 Item 对象。(套餐可以任意搭配)

import java.util.ArrayList;
import java.util.List;

public class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }
    }
}

(6)创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。

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 ChickBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

(7)演示建造者模式

public class Main {
    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("

Non-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }
}

演示结果:

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

5、原型模式

原型模式是指通过调用原型实例的Clone方法或其他手段来创建对象。

原型模式的Java实现只需原型类实现Cloneable接口并覆盖clone方法即可。

以使用 ShapeCache 类来获取 Shape 对象:

(1)创建一个实现了 Cloneable 接口的抽象类。

public abstract class Shape implements Cloneable {
    private String id;
    protected String type;
    abstract void draw();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Object clone(){
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

(2)创建扩展上面抽象类的实体类。

public class Circle extends Shape {
    public Circle(){
        type = "Circle";
    }

    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

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.");
    }
}

(3)创建一个类,从数据库获取实体类,并把它们存储在一个 Hashtable 中。

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);
    }
}

(4)使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。

public class Main {
    public static void main(String[] args) {
        ShapeCache.loadCache();

        Shape clonedShape = (Shape) ShapeCache.getShape("1");
        clonedShape.draw();
        System.out.println("Shape : " + clonedShape.getType() );

        Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
        clonedShape2.draw();
        System.out.println("Shape : " + clonedShape2.getType());

        Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
        clonedShape3.draw();
        System.out.println("Shape : " + clonedShape3.getType());
    }
}
原文地址:https://www.cnblogs.com/strong-FE/p/12114687.html