图解设计模式

Iterator 模式

如果使用具体的类来解决问题,很容易导致类之间的强耦合,这些类也难以作为组件被再次利用,为了弱化类之间的耦合,进而使得类更加容易作为组件被再次利用,需要引入抽象类和接口

image.png
public interface Aggregate {
    public abstract Iterator iterator();
}

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}

public class BookShelf implements Aggregate {

    private Book[] books;
    private int last;

    BookShelf(int maxSize) {
        books = new Book[maxSize];
        last = 0;
    }

    Book getBookAt(int index) {
        return books[index];
    }

    void appendBook(Book book) {
        books[last++] = book;
    }

    int getLength() {
        return last;
    }

    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}

public class Book {
    private String name;
    Book(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }
}

public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;
    BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        index = 0;
    }

    @Override
    public boolean hasNext() {
        return index < bookShelf.getLength();
    }

    @Override
    public Object next() {
        return bookShelf.getBookAt(index++);
    }
}

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);
        bookShelf.appendBook(new Book("Around the World in 80 Days"));
        bookShelf.appendBook(new Book("Bible"));
        bookShelf.appendBook(new Book("Cinderella"));
        bookShelf.appendBook(new Book("Daddy-Long-Legs"));
        Iterator it = bookShelf.iterator();
        while (it.hasNext()) {
            Book book = (Book)it.next();
            System.out.println(book.getName());
        }
    }
}

/* output
Around the World in 80 Days
Bible
Cinderella
Daddy-Long-Legs
*/

Adapter 模式

类适配器

image.png

使用 Print 接口来编程,对 Main 类来说,隐藏了 Banner 类的方式,Main 不知道 PrintBanner 是如何实现的,可以不对 Main 修改的情况下,修改 PrintBanner 的实现

public class Banner {
    private String name;

    Banner(String name) {
        this.name = name;
    }

    void showParen() {
        System.out.println("(" + name + ")");
    }

    void showAster() {
        System.out.println("*" + name + "*");
    }

}

public interface Print {
    public void printWeak();
    public void printStrong();
}

public class PrintBanner extends Banner implements Print {

    PrintBanner(String name) {
        super(name);
    }

    @Override
    public void printWeak() {
        showParen();
    }

    @Override
    public void printStrong() {
        showAster();
    }
}

对象适配器

image.png
public abstract class Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

public class PrintBanner extends Print  {

    private Banner banner;
    PrintBanner(String name) {
        banner = new Banner(name);
    }

    @Override
    public void printWeak() {
        banner.showParen();
    }

    @Override
    public void printStrong() {
        banner.showAster();
    }
}

Template Method 模式

在父类中现实的处理流程,在子类中实现, display 方法调用了由子类实现的 open,print, close 方法

image.png
image.png
public abstract class AbstractDisplay {
    public abstract void open();
    public abstract void print();
    public abstract void close();
    public final void display() {
        open();
        for (int i = 0; i < 5; i++) {
            print();
        }
        close();
    }
}

public class CharDisplay extends AbstractDisplay {
    private char ch;
    public CharDisplay(char ch) {
        this.ch = ch;
    }

    @Override
    public void open() {
        System.out.print("<<<");
    }

    @Override
    public void print() {
        System.out.print(ch);
    }

    @Override
    public void close() {
        System.out.println(">>>");
    }
}

Factory Method

Factory 模式中,父类决定实例的生成方式,并不决定生成的具体的类,具体的类
全部交给子类负责

image.png
public abstract class Factory {
    public final Product create(String string) {
        Product p = createProduct(string);
        registerProduct(p);
        return p;
    }

    protected abstract  Product createProduct(String string);
    protected abstract void registerProduct(Product p);
}

public class IDCardFactory extends Factory {
    private List owners = new ArrayList();
    @Override
    protected Product createProduct(String string) {
        return new IDCard(string);
    }

    @Override
    protected void registerProduct(Product p) {
        owners.add(p);
    }
}

public class IDCard extends Product {
    private String id;

    IDCard(String id) {
        this.id = id;
    }

    @Override
    public void use() {
        System.out.println(id);
    }
}

public abstract class Product {
    public abstract void use();
}

Prototype 模式

  • 对象种类繁多,无法将它们整合到一个类中
  • 难以根据类生成实例
  • 想解耦框架与生成的实例
image.png
public interface Product extends Cloneable {
    public abstract void use(String s);
    public Product createClone();
}

public class Manager {
    private HashMap showcase = new HashMap();
    public void register(String key, Object value) {
        showcase.put(key, value);
    }

    public Product create(String key) {
        Product p = (Product)showcase.get(key);
        return p.createClone();
    }
}

public class MessageBox implements Product {
    private char decochar;
    public MessageBox(char decochar) {
        this.decochar = decochar;
    }

    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }

        System.out.println("");
        System.out.println(decochar + " " + s + " " + decochar);
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
    }


    @Override
    public Product createClone() {
        Product p = null;
        try {
            p = (Product)clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

public class UnderlinePen implements Product {
    private char ulchar;
    public UnderlinePen(char ulchar) {
        this.ulchar = ulchar;
    }

    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("\"" + s + "\"");
        System.out.print(" ");
        for (int i = 0; i < length; i ++) {
            System.out.print(ulchar);
        }
        System.out.println("");
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product)clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

public class Main {
    public static void main(String[] args) {
        Manager mgr = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox sbox = new MessageBox('/');
        mgr.register("strong message", upen);
        mgr.register("warning box", mbox);
        mgr.register("slash box", sbox);

        Product p1 = mgr.create("strong message");
        p1.use("Hello, world");

        Product p2 = mgr.create("warning box");
        p2.use("Hello, world");

        Product p3 = mgr.create("slash box");
        p3.use("Hello, world");
    }
}


/* output
"Hello, world"
 ~~~~~~~~~~~~
****************
* Hello, world *
****************
////////////////
/ Hello, world /

*/

Builder 模式

组装具有复杂结构的实例 Builder 模式

image.png
public abstract class Builder {
    public abstract void makeTitle(String title);
    public abstract void makeString(String str);
    public abstract void makeItems(String[] items);
    public abstract void close();
}

public class Director {
    private Builder builder;
    public Director(Builder builer) {
        this.builder = builer;
    }

    public void construct() {
        builder.makeTitle("Greeting");
        builder.makeString("从早上到下午");
        builder.makeItems(new String[] {
                "早上好",
                "下午好",
        });

        builder.makeString("晚上");
        builder.makeItems(new String[] {
                "晚上好",
                "晚安",
                "再见"
        });
        builder.close();
    }
}

public class Main {
    public static void main(String[] args) {
        TextBuilder textBuilder = new TextBuilder();
        Director director = new Director(textBuilder);
        director.construct();
        System.out.println(textBuilder.getResult());
    }
}

/*
========

*从早上到下午

   .早上好
   .下午好

*晚上

   .晚上好
   .晚安
   .再见

========
*/

Abstract Factory 模式

抽象工厂的工作是将 “抽象零件” 组成为 “抽象产品”,我们并不关心零件的具体实现,而是只关心接口。仅适用该接口把零件组装成产品

image.png

抽象的零件: Item 类

/*
* Item 有 caption 表示标题
* makeHTML 方法是抽象方法,让子类实现
* */
public abstract class Item {
    protected String caption;
    
    public Item(String caption) {
        this.caption = caption;
    }
    
    public abstract String makeHTML();
}

抽象的零件: Link 类

public abstract class Link extends Item {
    protected String url;
    public Link(String caption, String url) {
        super(caption);
        this.url = url;
    }
}

抽象的零件: Tray 类

/*
* Tray 类表示的是一个含有多个 Link 类和 Tray 类的容器。
* */
public abstract class Tray extends Item {
    protected ArrayList tray = new ArrayList();

    public Tray(String caption) {
        super(caption);
    }

    public void add(Item item) {
        tray.add(item);
    }
}

抽象的产品: Page 类


/*
* Page 类是抽象地表示 HTML 页面的类,抽象产品
* */
public abstract class Page {
    protected String title;
    protected String author;
    protected ArrayList content = new ArrayList();
    public Page(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public void add(Item item) {
        content.add(item);
    }

    public void output() {
        try {
            String filename = title + ".html";
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public abstract String makeHTML();

}

抽象的工厂: Factory 类

public abstract class Factory {
    public static Factory getFactory(String classname) {
        Factory factory = null;
        try {
            factory = (Factory)Class.forName(classname).newInstance();
        } catch (ClassNotFoundException e) {

        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }

    public abstract Link createLink(String caption, String url);
    public abstract Tray createTray(String caption);
    public abstract Page createPage(String title, String author);
}

具体工厂类: ListFactory

/*
* 生成零件和产品
* */
public class ListFactory extends Factory {
    public Link createLink(String caption, String url) {
        return new ListLink(caption, url);
    }
    public Tray createTray(String caption) {
        return new ListTray(caption);
    }
    public Page createPage(String title, String author) {
        return new ListPage(title, author);
    }
}

具体的零件: ListLink 和 ListTray

public class ListLink extends Link {
    public ListLink(String caption, String url) {
        super(caption, url);
    }

    @Override
    public String makeHTML() {
        return "  <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
    }
}

public class ListTray extends Tray {
    public ListTray(String caption) {
        super(caption);
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<li>\n");
        buffer.append(caption + "\n");
        buffer.append("<ul>\n");
        Iterator it = tray.iterator();
        while (it.hasNext()) {
            Item item = (Item)it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("</li>\n");
        return buffer.toString();
    }
}


具体产品类: ListPage

import java.util.Iterator;

public class ListPage extends Page {
    public ListPage(String title, String author) {
        super(title, author);
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<html><head><title>" + title + "</title></head>\n");
        buffer.append("<body>\n");
        buffer.append("<h1>" + title + "</h1>\n");
        buffer.append("<ul>\n");
        Iterator it = content.iterator();
        while (it.hasNext()) {
            Item item = (Item)it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}

Main

通过抽象零件,抽象产品,抽象工厂,可以方便的通过这个模式产生各种产品,通过子类,的实现不同,来实现,不同产品,不同工厂的实现,能产生不同的产品。

public class Main {
    public static void main(String[] args) {
        Factory factory = Factory.getFactory("ListFactory");

        Link baidu = factory.createLink("百度", "http://www.baidu.com/");

        Link bing = factory.createLink("bing", "https://cn.bing.com/");

        Tray tray1 = factory.createTray("1");
        Tray tray2 = factory.createTray("2");

        tray1.add(baidu);
        tray2.add(bing);

        Page page = factory.createPage("LinkPage", "ptyuan");
        page.add(tray1);
        page.add(tray2);
        page.output();
    }
}

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

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,605评论 18 399
  • 本文首发于个人博客:Lam's Blog - 谈谈23种设计模式在Android源码及项目中的应用,文章由Mark...
    格子林ll阅读 4,638评论 1 105
  • 组成模版的方法被定义在父类中,这些方法是抽象方法,所以只查看父类的代码是无法知道这些方法最终会进行何种具体的处理,...
    MWY阅读 406评论 1 0
  • 在Factory Method模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理全部交给子类...
    MWY阅读 439评论 0 2
  • 青岛市民免费试乘地铁的最后一天,那天清晨,我带上八十多岁的父亲来到了车站,专程让老人体验一回城市轨道交通的"...
    牧言1阅读 389评论 0 0