设计模式总结干货2

如果想学习Java工程化、高性能及分布式、深入浅出。性能调优、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级架构进阶群:180705916,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家

另外还可以通过反射简洁生产过程,直接传入产品的类类型,生成对应的产品,示例如下:

Java代码

abstract class SMakeTea {  

    public abstract  T 小猪带特效的奶茶制作工艺(Class clz);  

}  

class SMe extends SMakeTea {  

    @Override  

    public  T 小猪带特效的奶茶制作工艺(Class clz) {  

        System.out.println("==============");  

        Tea tea = null;  

        try {  

            tea = (Tea) Class.forName(clz.getName()).newInstance();  

            tea.加奶();  

            tea.加茶();  

            tea.加料();  

            tea.打包();  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

        return (T) tea;  

    }  

}  

public class SStore {  

    public static void main(String[] args) {  

        SMe me = new SMe();  

        me.小猪带特效的奶茶制作工艺(ZhenZhuTea.class);  

        me.小猪带特效的奶茶制作工艺(YeGuoTea.class);  

    }  

}

六. 抽象工厂模式(Abstract Factory Pattern)

代码示例

Java代码

//抽象产品类1  

abstract class Drink {  

    public abstract void drink();  

}  

//抽象产品类2  

abstract class Snack {  

    public abstract void snack();  

}  

//具体产品类们  

class MilkTea extends Drink {  

    @Override public void drink() { System.out.println("一杯奶茶"); }  

}  

class Juice extends Drink {  

    @Override public void drink() { System.out.println("一杯果汁"); }  

}  

class HandGrab extends Snack {  

    @Override public void snack() { System.out.println("一个手抓饼"); }  

}  

class FishBall extends Snack {  

    @Override public void snack() { System.out.println("一碗鱼蛋"); }  

}  

//抽象工厂类  

abstract class MakeFood {  

    abstract Drink createMakeDrink();  

    abstract Snack createMakeSnack();  

}  

//具体工厂类1  

class FirstXiaoDi extends MakeFood {  

    @Override public Drink createMakeDrink() { return new MilkTea(); }  

    @Override public Snack createMakeSnack() { return new HandGrab(); }  

}  

//具体工厂类2  

class SecondXiaoDi extends MakeFood {  

    @Override public Drink createMakeDrink() { return new Juice(); }  

    @Override public Snack createMakeSnack() { return new FishBall(); }  

}  

//客户端调用  

public class Store {  

    public static void main(String[] args) {  

        //初始化两个小弟  

        MakeFood xiaodi1 = new FirstXiaoDi();  

        MakeFood xiaodi2 = new SecondXiaoDi();  

        for(int i = 0;i < 4 ;i++) {  

            System.out.println("====== 根据订单配餐: ======");  

            Drink drink = buyDrink() == 0 ?  

                xiaodi1.createMakeDrink() : xiaodi2.createMakeDrink();  

            Snack snack = buySnack() == 0 ?   

                xiaodi1.createMakeSnack() : xiaodi2.createMakeSnack();  

            drink.drink();  

            snack.snack();  

        }  

    }  

    /* 模拟用户点饮料,0代表要奶茶,1代表要果汁 */  

    private static int buyDrink() { return new Random().nextInt(2); }  

    /* 模拟用户点小吃,0代表要手抓饼,1代表要鱼蛋 */  

    private static int buySnack() { return new Random().nextInt(2); }  

}

输出结果

两个名词(产品等级结构产品族)

产品等级结构(继承)

比如这里的抽象类是Drink(饮料),子类有奶茶,果汁,然后抽象饮料与具体饮料构成了一个产品等级结构,抽象饮料是父类,具体饮料是其子类。

产品族

同一工厂生产的,位于不同产品等级结构的一组产品,比如这里的奶茶和果汁属于饮料结构的一组产品,而手抓饼和鱼蛋则属于小吃结构的一组产品。

四个角色与UML类图

抽象工厂模式适用于创建的对象有多个相互关联或依赖的产品族;抽象工厂模式隔离具体类的生成,接口与实现分离,增加新的产品族很方便;但是扩展新的产品等级结构麻烦,需要修改抽象工厂,具体工厂类也要更改。

七. 适配器模式(Adapter Pattern)

两个彼此间没太大关联的类,想进行交互完成某些事情,不想直接去修改各自的接口,可以添加一个中间类,让他来协调两个类间的关系,完成相关业务,这种模式就叫适配器模式。

然后分为:类适配器对象适配器两种,前者和适配者是继承关系,后者与适配者则是引用关系。

对象适配器支持传入一个被适配器对象,因此可以做到对多种被适配接口进行适配。而类适配器直接继承无法动态修改,所以一般情况下对象适配器使用得更多!(Java不支持多重继承!!!)

对象适配器例子(用得较多)

Java代码

/* 目标接口 */  

interface Chinese {  

    void speakChinese(String string);  

}  

/* 需要适配的类 */  

class English {  

    void speakEnglish(String string) { System.out.println("【英语】" + string); }  

}  

/* 适配器 */  

class Translator implements Chinese{  

    private English english = new English();  

    Translator(English english) { this.english = english; }  

    @Override public void speakChinese(String string) { english.speakEnglish(string); }  

}  

/* 客户端调用 */  

public class Client {  

    public static void main(String[] args) {  

        Chinese chinese = new Translator(new English());  

        chinese.speakChinese("那你很棒棒哦!");  

    }  

输出结果

类适配器例子

Java代码

/* 类适配器 */  

class ClassTranslator extends English implements Chinese {  

    @Override public void speakChinese(String string) { speakEnglish(string); }  

}  

/* 客户端调用 */  

public class ClientC {  

    public static void main(String[] args) {  

        ClassTranslator translator = new ClassTranslator();  

        translator.speakChinese("你也很好啊!");  

    }  

输出结果

除此之外还有个缺省适配器模式的名词,简单点说就是不需要实现接口中提供的所有方法时,先写一个抽象类实现这个接口,然后为每个方法提供一个默认实现(空方法),然后选择性覆盖某些方法实现需求,又称单接口适配器模式。

八.装饰者模式(Decorator Pattern)

动态的给对象添加一些额外的职责,就增加功能来说,装饰者模式比起生成子类更加灵活!就是想替代多重层继承的模式。其实就是一层套一层

代码示例

Java代码

/* 抽象组件 */  

abstract class Tea {  

    private String name = "茶";  

    public String getName() { return name; }  

    void setName(String name) { this.name = name; }  

    public abstract int price();  

}  

/* 具体组件 */  

class MilkTea extends Tea {  

    MilkTea() { setName("奶茶"); }  

    @Override public int price() { return 5; }  

}  

class LemonTea extends Tea{  

    LemonTea() { setName("柠檬茶"); }  

    @Override public int price() { return 3; }  

}  

/* 抽象装饰类 */  

abstract class Decorator extends Tea{  

    public abstract String getName();  

}  

/* 具体装饰类 */  

class ZhenZhu extends Decorator {  

    Tea tea;  

    ZhenZhu(Tea tea) { this.tea = tea; }  

    @Override public String getName() { return "珍珠" + tea.getName(); }  

    @Override public int price() { return 2 + tea.price(); }  

}  

class YeGuo extends Decorator{  

    //...  

}  

class JinJu extends Decorator{  

    //...  

}  

class HongDou extends Decorator{  

    //...  

}  

/* 客户端调用 */  

public class Store {  

    public static void main(String[] args) {  

        Tea tea1 = new MilkTea();  

        System.out.println("你点的是:" + tea1.getName() + " 价格为:" + tea1.price());  

        Tea tea2 = new LemonTea();  

        tea2 = new JinJu(tea2);  

        System.out.println("你点的是:" + tea2.getName() + " 价格为:" + tea2.price());  

        Tea tea3 = new MilkTea();  

        tea3 = new ZhenZhu(tea3);  

        tea3 = new YeGuo(tea3);  

        tea3 = new HongDou(tea3);  

        tea3 = new JinJu(tea3);  

        System.out.println("你点的是:" + tea3.getName() + " 价格为:" + tea3.price());  

    }  

}

输出结果

九.组合模式(Composite Pattern)

部分-整体模式,把具有相似的一组对象当做一个对象处理,用一种树状的结构组合对象,再提供统一的方法去访问相似的对象,以此忽略掉对象与对象容器间的差别。

根节点枝结点叶子结点三个名词需要理解,类比上图,根节点是菜单,枝结点是饮料菜单和小吃菜单,叶子结点是奶茶,果汁,手抓饼和鱼蛋!

代码示例

Java代码

/* 抽象组件 */  

abstract class AbstractMenu {  

    public abstract void add(AbstractMenu menu);  

    public abstract AbstractMenu get(int index);  

    public abstract String getString();  

}  

/* 容器组件 */  

class Menu extends AbstractMenu {  

    private String name;  

    private String desc;  

    private List menus = new ArrayList<>();  

    Menu(String name, String desc) {  

        this.name = name;  

        this.desc = desc;  

    }  

    @Override public void add(AbstractMenu menu) { menus.add(menu); }  

    @Override public AbstractMenu get(int index) { return menus.get(index); }  

    @Override public String getString() {  

        StringBuilder sb = new StringBuilder("\n【菜单】:" + name + " 信息:" + desc + "\n");  

        for (AbstractMenu menu: menus) { sb.append(menu.getString()).append("\n"); }  

        return sb.toString();  

    }  

}  

/* 叶子组件 */  

class MilkTea extends AbstractMenu {  

    private String name;  

    private String desc;  

    private int price;  

    MilkTea(String name, String desc, int price) {  

        this.name = name;  

        this.desc = desc;  

        this.price = price;  

    }  

    @Override public void add(AbstractMenu menu) { /*未使用*/ }  

    @Override public AbstractMenu get(int index) { return null; }  

    @Override public String getString() {  

        return " - 【奶茶】* " + name + " 标注:" + desc + " 价格:" + price;  

    }  

}  

class MilkTea extends AbstractMenu {  

    //...  

}  

class HandCake  extends AbstractMenu {  

    //...  

}  

class FishBall  extends AbstractMenu {  

    //...  

}  

/* 客户端调用 */  

public class Store {  

    public static void main(String[] args) {  

        AbstractMenu mainMenu = new Menu("大菜单", "包含所有子菜单");  

        AbstractMenu drinkMenu = new Menu("饮品菜单", "都是喝的");  

        AbstractMenu eatMenu = new Menu("小吃菜单", "都是吃的");  

        AbstractMenu milkTea = new MilkTea("珍珠奶茶", "奶茶+珍珠", 5);  

        AbstractMenu juice = new Juice("鲜榨猕猴桃枝", "无添加即榨", 8);  

        AbstractMenu ball = new FishBall("咖喱鱼蛋", "微辣", 6);  

        AbstractMenu cake = new HandCake("培根手抓饼", "正宗台湾风味", 8);  

        drinkMenu.add(milkTea);  

        drinkMenu.add(juice);  

        eatMenu.add(ball);  

        eatMenu.add(cake);  

        mainMenu.add(drinkMenu);  

        mainMenu.add(eatMenu);  

        System.out.println(mainMenu.getString());  

    }  

}

输出结果

十.桥接模式(Bridge Pattern)

基于单一职责原则,如果系统中的类存在多个变化的维度,通过该模式可以将这几个维度分离出来, 然后进行独立扩展。这些分离开来的维度,通过在抽象层持有其他维度的引用来进行关联,就好像在两个维度间搭了桥一样,所以叫桥接模式。

代码示例(变化的三个维度:配餐,扒类)

Java代码

/* 抽象部分 */  

abstract class Rations {  

    abstract String rations();  

}  

/* 扩展抽象部分 */  

class Rice extends Rations {  

    @Override public String rations() { return "饭"; }  

}  

class Spaghetti extends Rations {  

    @Override public String rations() { return "意粉"; }  

}  

/* 实现部分 */  

abstract class Steak {  

    Rations rations;  

    Steak(Rations rations) { this.rations = rations; }  

    abstract String sale();  

}  

/* 具体实现部分 */  

class BeefSteak extends Steak{  

    BeefSteak(Rations rations) { super(rations); }  

    @Override public String sale() { return "牛扒"+ (rations == null ? "" : rations.rations()); }  

}  

class PorkSteak extends Steak {  

    PorkSteak(Rations rations) { super(rations); }  

    @Override public String sale() { return "猪扒"+ (rations == null ? "" : rations.rations()); }  

}  

/* 客户端调用 */  

public class Restaurant {  

    public static void main(String[] args) {  

        System.out.println("\n" + new Date(System.currentTimeMillis()));  

        System.out.println("==================");  

        Steak steak1 = new BeefSteak(new Rice());  

        System.out.println("卖出了一份:" + steak1.sale());  

        Steak steak2 = new PorkSteak(new Spaghetti());  

        System.out.println("卖出了一份:" + steak2.sale());  

        Steak steak3 = new PorkSteak(null);  

        System.out.println("卖出了一份:" + steak3.sale());  

         System.out.println("==================");  

输出结果

十一.外观模式(Facade Pattern)

要求一个子系统的外部与内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统更易于使用。(其实就是封装,用于解决类与类间的依赖关系,比如本来是:玩家依赖于:Q,A,E,R等键位对象,现在变成只依赖与脚本对象从而降低了类间的耦合度。)

代码示例

Java代码

/* 子系统 */  

class A {  

    String a() { return "A"; }  

}  

class Q { /* ... */ }  

class Space { /* ... */ }  

class LeftClick { /* ... */ }  

/* 外观类 */  

class JiaoBen {  

    A a;  

    Q q;  

    LeftClick leftClick;  

    Space space;  

    JiaoBen() {  

        a = new A();  

        leftClick = new LeftClick();  

        q = new Q();  

        space = new Space();  

    }  

    String 锐雯() {  

        StringBuilder sb = new StringBuilder();  

        sb.append(q.q()).append(" + ");  

        sb.append(space.space()).append(" + ");  

        sb.append(a.a()).append(" + ");  

        sb.append(leftClick.leftClick()).append(" + ");  

        sb.append(q.q()).append(" + ");  

        sb.append(space.space()).append(" + ");  

        sb.append(a.a()).append(" + ");  

        sb.append(leftClick.leftClick()).append(" + ");  

        sb.append(q.q()).append(" + ");  

        sb.append(space.space()).append(" + ");  

        sb.append(a.a()).append(" + ");  

        sb.append(leftClick.leftClick()).append("\n");  

        return sb.toString();  

    }  

}  

/* 客户端调用 */  

public class XLoLer {  

    public static void main(String[] args) {  

        JiaoBen jiaoBen = new JiaoBen();  

        System.out.println("=== 锐雯一键光速QA ===\n" + jiaoBen.锐雯());  

    }  

}

输出结果

十二. 享元模式(Flyweight Pattern)

当存在多个相同对象时,可以使用享元模式减少相同对象创建引起的内存消耗,提高程序性能。说到共享,还分内部状态与外部状态

内部状态固定不变可共享的的部分,存储在享元对象内部,比如例子中的花色

外部状态可变不可共享的部分,一般由客户端传入享元对象内部,比如例子里的大小

示例代码

Java代码

/* 抽象对象的父类 */  

abstract class Card {  

    abstract void showCard(String num);  //传入外部状态参数,大小  

}  

/* 具体享元对象 */  

public class SpadeCard extends Card{  

    public SpadeCard() { super(); }  

    @Override public void showCard(String num) { System.out.println("黑桃:" + num); }  

}  

public class HeartCard extends Card { /* ... */ }  

public class ClubCard extends Card { /* ... */ }  

public class DiamondCard extends Card { /* ... */ }  

/* 享元工厂 */  

public class PokerFactory {  

    static final int Spade = 0;  //黑桃  

    static final int Heart  = 1; //红桃  

    static final int Club  = 2; //梅花  

    static final int Diamond  = 3;   //方块  

    public static Map pokers = new HashMap<>();  

    public static Card getPoker(int color) {  

        if (pokers.containsKey(color)) {  

            System.out.print("对象已存在,对象复用...");  

            return pokers.get(color);  

        } else {  

            System.out.print("对象不存在,新建对象...");  

            Card card;  

            switch (color) {  

                case Spade: card = new SpadeCard(); break;  

                case Heart: card = new HeartCard(); break;  

                case Club: card = new ClubCard(); break;  

                case Diamond: card = new DiamondCard(); break;  

                default: card = new SpadeCard(); break;  

            }  

            pokers.put(color,card);  

            return card;  

        }  

    }  

/* 客户端调用 */  

public class Player {  

    public static void main(String[] args) {  

        for (int k = 0; k < 10; k ++){  

            Card card = null;  

            //随机花色  

            switch ((int)(Math.random()*4)) {  

                case 0: card = PokerFactory.getPoker(PokerFactory.Spade); break;  

                case 1: card = PokerFactory.getPoker(PokerFactory.Heart); break;  

                case 2: card = PokerFactory.getPoker(PokerFactory.Club); break;  

                case 3: card = PokerFactory.getPoker(PokerFactory.Diamond); break;  

            }  

            if(card != null) {  

                //随机大小  

                int num = (int)(Math.random()*13 + 1);  

                switch (num) {  

                    case 11: card.showCard("J"); break;  

                    case 12: card.showCard("Q"); break;  

                    case 13: card.showCard("K"); break;  

                    default: card.showCard(num+""); break;  

                }  

            }  

        }  

    }  

输出结果

未完待续。。。

你可能感兴趣的:(设计模式总结干货2)