设计模式二(创建型模式)

引用:runoob.com 设计模式

一, 工厂模式(Factory Pattern)

定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

案例:
1, 接口

public interface Fruit {
    String price();
}

2,三个实现类

public class Apple implements Fruit {
    @Override
    public String price() {
        return "苹果:10元/斤";
    }
}

public class Banana implements Fruit {
    @Override
    public String price() {
        return "香蕉:20元/斤";
    }
}

public class Pear implements Fruit {
    @Override
    public String price() {
        return "梨: 5元/斤";
    }
}

3,工厂类 根据参数名创建对象

public class FruitFactory {
    public Fruit getFruit(String name) {
        if (StringUtils.equals(name, "apple")) {
            return new Apple();
        } else if (StringUtils.equals(name, "banana")) {
            return new Banana();
        } else if (StringUtils.equals(name, "pear")) {
            return new Pear();
        } else {
            return null;
        }
    }
}

4,测试

public class Demo {
    public static void main(String[] args) {
        FruitFactory factory = new FruitFactory();
        // 苹果
        Fruit apple = factory.getFruit("apple");
        System.out.println(apple.price());
        // 香蕉
        Fruit banana = factory.getFruit("banana");
        System.out.println(banana.price());
        // 梨
        Fruit pear = factory.getFruit("pear");
        System.out.println(pear.price());
    }
}
打印结果: 
苹果:10元/斤
香蕉:20元/斤
梨: 5元/斤

二, 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂

案例:
1, 图形的接口, 实现类

public interface Shape {
    void draw();
}
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个圈");
    }
}
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个方形");
    }
}

2, 颜色的接口, 实现类

public interface Color {
    void fill();
}
public class Red implements Color {
    @Override
    public void fill() {
        System.out.println("填充了红色");
    }
}
public class Green implements Color {
    @Override
    public void fill() {
        System.out.println("填充了绿色");
    }
}

3, 抽象工厂, 工厂提供者, 颜色工厂, 图形工厂

public abstract class AbstractFactory {
    public abstract Shape getShape(String name);
    public abstract Color getColor(String name);
}

public class FactoryProducer {
    public AbstractFactory getFactory(String factoryName){
        if(StringUtils.equals(factoryName, "color")) {
            // 颜色工厂
            return new ColorFactory();
        } else if(StringUtils.equals(factoryName, "shape")) {
            // 图形工厂
            return new ShapeFactory();
        }
        return null;
    }
}

public class ColorFactory extends AbstractFactory {
    @Override
    public Shape getShape(String name) {
        return null;
    }
    @Override
    public Color getColor(String name) {
        if (StringUtils.equals(name, "red")) {
            return new Red();
        } else if (StringUtils.equals(name, "green")) {
            return new Green();
        }
        return null;
    }
}

public class ShapeFactory extends AbstractFactory {
    @Override
    public Shape getShape(String name) {
        if (StringUtils.equals(name, "circle")) {
            return new Circle();
        } else if (StringUtils.equals(name, "square")) {
            return new Square();
        }
        return null;
    }
    @Override
    public Color getColor(String name) {
        return null;
    }
}

4, demo

public static void main(String[] args) {
        FactoryProducer producer = new FactoryProducer();
        // 画图形
        AbstractFactory shapeFactory = producer.getFactory("shape");
        Shape circle = shapeFactory.getShape("circle");
        circle.draw();
        Shape square = shapeFactory.getShape("square");
        square.draw();
        // 填充颜色
        AbstractFactory colorFactory = producer.getFactory("color");
        Color red = colorFactory.getColor("red");
        red.fill();
        Color green = colorFactory.getColor("green");
        green.fill();
    }

打印结果:
画一个圈
画一个方形
填充了红色
填充了绿色

三, 单例模式(Singleton Pattern)

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

案例:
1, 饿汉式

public class SingleObject {
    // 全局就一个对象
    private static SingleObject instance = new SingleObject();
    // 私有化构造器, 外界不能new对象
    private SingleObject(){}
    // 获取对象
    public static SingleObject getInstance(){
        return instance;
    }
}

2, 懒汉式 (延迟加载)

public class SingleObjectB {

    // 全局就一个对象
    private static SingleObjectB instance = null;

    // 私有化构造器, 外界不能new对象
    private SingleObjectB(){}
    // 获取对象
    public static SingleObjectB getInstance(){
        // 此处需要双重判断,防止多次创建对象
        if (null == instance) {
            synchronized (SingleObjectB.class) {
                if (null == instance) {
                    instance = new SingleObjectB();
                }
            }
        }
        return instance;
    }
}

3, 静态内部类(申明式)

public class SingleObjectC {
    // 内部类
    private static class SingleHolder{
        private static final SingleObjectC singleObjectC = new SingleObjectC();
    }

    private SingleObjectC(){}
    
    public static SingleObjectC getInstance(){
        return SingleHolder.singleObjectC;
    }

}

4, 枚举(实现单例模式的最佳方法)

public class SingleObjectD {

    private SingleObjectD(){}

    public static SingleObjectD getInstance(){
        return SingleEnum.INSTENCE.getInstence();
    }

    private enum SingleEnum{
        INSTENCE,
        ;
        private SingleObjectD singleObjectD;
        // JVM保证此方法只执行一次
        SingleEnum(){
            singleObjectD = new SingleObjectD();
        }

        private SingleObjectD getInstence(){
            return singleObjectD;
        }
    }
}

四, 建造者模式(Builder Pattern)

使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。如StringBuilder

案例: 如肯德基套餐, 食物不变, 可以有多种组合
食物接口:

public interface Item {
    // 食物名
    String name();
    // 食物价格
    float price();
    // 包装类型
    Packing pack();
}

包装类型:

public interface Packing {
    // 包装
    String name();
}
public class Wrapper implements Packing {

    @Override
    public String name() {
        return "纸包装";
    }
}
public class Bottle implements Packing {
    @Override
    public String name() {
        return "瓶子包装";
    }
}

汉堡类型:

public abstract class Burger implements Item {
    @Override
    public Packing pack() {
        // 所有汉堡都是纸包装的
        return new Wrapper();
    }
}
public class VegBurger extends Burger {
    @Override
    public String name() {
        return "蔬菜汉堡";
    }
    @Override
    public float price() {
        return 20.0f;
    }
}
public class ChickenBurger extends Burger {
    @Override
    public String name() {
        return "鸡肉汉堡";
    }
    @Override
    public float price() {
        return 12.0f;
    }
}

饮料类型:

public abstract class Drink implements Item {
    @Override
    public Packing pack() {
        // 所有饮料都是瓶子包装的
        return new Bottle();
    }
}
public class Milk extends Drink {
    @Override
    public String name() {
        return "牛奶";
    }
    @Override
    public float price() {
        return 8.0f;
    }
}
public class Coke extends Drink {
    @Override
    public String name() {
        return "可乐";
    }
    @Override
    public float price() {
        return 5.0f;
    }
}

套餐:

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

    public void addItem(Item item) {
        meal.add(item);
    }
    public float getPrice(){
        float price = 0f;
        for (Item item : meal) {
            price += item.price();
        }
        return price;
    }
    public void showItems(){
        for (Item item : meal) {
            System.out.println("食物:" + item.name() + " 包装:" + item.pack().name() + " 价格:" + item.price());
        }
        System.out.println("总价:" + getPrice());
    }
}

套餐建造者

public class MealBuilder {
    public Meal buildVegMeal(){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Milk());
        return meal;
    }
    public Meal buildChickenMeal(){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Coke());
        return meal;
    }
}

Demo

public static void main(String[] args) {
        MealBuilder builder = new MealBuilder();
        // 蔬菜套餐
        Meal meal = builder.buildVegMeal();
        meal.showItems();
        // 鸡肉套餐
        Meal meal2 = builder.buildChickenMeal();
        meal2.showItems();
    }

五, 原型模式(Prototype Pattern)

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

图形类:

public abstract class Shap implements Cloneable{

    protected String name;
    abstract void draw();

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    protected Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class Square extends Shap {

    public Square(){
        name = "方形";
    }

    @Override
    void draw() {
        System.out.println("画一个正方形");
    }
}

缓存

public class ShapCache {

    private HashMap<String, Shap> cache = new HashMap<String, Shap>();

    public void loadCache(){
        Square square = new Square();
        cache.put("square", square);
    }

    public Shap getShap(String key){
        return (Shap)cache.get(key).clone();
    }
}

Demo

public static void main(String[] args) {
        ShapCache cache = new ShapCache();
        cache.loadCache();
        Shap square = cache.getShap("square");
        square.draw();
        // 方形
        System.out.println(square.getName());
        square.setName("haahha");
        // haahha
        System.out.println(square.getName());
        Shap square2 = cache.getShap("square");
        // 方形
        System.out.println(square2.getName());
    }

注意, 使用clone方法拷贝对象为浅拷贝, 根据需要做深拷贝处理.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343