ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式学习(1)适应设计模式

2022-08-13 15:30:46  阅读:168  来源: 互联网

标签:学习 String Iterator void 适应 Book bookShelf 设计模式 public


迭代器模式

  • Iterator 迭代器接口

    public interface Iterator{
        boolean hasNext();	// 是否有下一个元素
        Object next();		// 返回下一个元素
    }
    
  • Aggregate 集合接口

    // 集合接口
    public interface Aggregate{
        Iterator iterator();
    }
    

例子

Iterator有个问题是:

  • 迭代器的next如何实现?保存集合的引用以及相关的信息,后面的例子会看到
  • 集合需要保存迭代器的引用吗? 不用,每次调用iterator获取迭代器的时候直接new一个就可以了

下面我们用迭代器模式来实现遍历书架上的书

class Book {
    private String name;

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

    @Override
    public String toString() {
        return name;
    }
}

class BookShelf implements Aggregate {
    private Book[] books;
    private int bookNumber;

    public BookShelf(int capacity) {
        books = new Book[capacity];
        bookNumber = 0;
    }

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

    public void addBook(Book book) {
        books[bookNumber++] = book;
    }

    public int length() {
        return bookNumber;
    }

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

class BookShelfIterator implements Iterator {

    private BookShelf bookShelf;
    private int index;

    BookShelfIterator(BookShelf shelf) {
        bookShelf = shelf;
        index = 0;
    }

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

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

// main函数
public class IteratorTest {
    public static void main(String[] args) {
        Book book1 = new Book("English");
        Book book2 = new Book("Math");
        Book book3 = new Book("Chinese");

        BookShelf bookShelf = new BookShelf(10);
        bookShelf.addBook(book1);
        bookShelf.addBook(book2);
        bookShelf.addBook(book3);

        Iterator bookIterator = bookShelf.iterator();
        while (bookIterator.hasNext()) {
            System.out.println(bookIterator.next());
        }
    }
}

角色

  • Iterator 迭代器接口
  • Aggregate 集合接口
  • 具体的Iterator,上例是BookShelfIterator
  • 具体的Aggregate,上例是BookShelf

注意

  • 引入迭代器后,可以将遍历单独分离开,因为遍历方式可能会有很多种,for循环遍历是最基础的一种。
  • Iterator会保存Aggregate的引用,所以它知道怎么在Aggregate中获取元素。那么当Aggregate获取元素的方法改变后,Iterator也要变
  • next不是返回下一个元素,而是返回当前,并指向下一个
  • 当next指向的元素超过了集合范围,hasNext就应该返回false
  • 迭代器可以next遍历,也可以previous遍历,有的还能跳跃式遍历

相关设计模式

  • 访问者模式Visitor
  • 组合模式Composite
  • 工厂方法Factory Method

适配器模式

我们现在想要实现printWeak和printStrong两个打印方法。这两个方法已经在Banner中实现了,但是接口不同。在Banner中实现的名字叫showWithParen和showWithAster。

现在我们想通过一个适配器,把这俩接口名改过来

// 横幅类
// 提供了两种显示的方法
// 但是这两个接口与我们希望的不符合
class Banner{
    private String string; // 横幅的内容
    public Banner(String str) {
        string = str;
    }

    // 圆括号显示
    public void showWithParen(){
        System.out.println("(" + string + ")");
    }

    // 星号显示
    public void showWithAster(){
        System.out.println("*" + string + "*");
    }
}

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

class PrintBanner extends Banner implements Print{

    public PrintBanner(String str) {
        super(str);
    }

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

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

public class AdaptorTest {
    public static void main(String[] args) {
        PrintBanner printBanner = new PrintBanner("ahahaha");
        printBanner.printWeak();
        printBanner.printStrong();
    }
}

上面这种实现方式是通过继承原类,并实现接口。下面还有一种是通过委托的方法

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

class PrintBanner extends Print{
    Banner banner;
    public PrintBanner(String str) {
        banner = new Banner(str);
    }

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

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

角色

继承版本的

委托版本的,与继承不同的地方是

  • Adapter不再是接口,而是抽象类
  • Adapter拥有了一个原类的对象

注意

  • 使用适配器是为了不修改源码,当我们需要使用某个库,但是又不是很喜欢它的接口,可以用适配器做一个包装。
  • 适配器的好处是,源库没有动,只需要测试适配器即可。只要源码动了,不管是改了什么,都需要做测试
  • 版本升级的时候,为了与旧版本兼容,可以在新版本上写一个适配器来适配旧版本。

相关设计模式

桥接模式:将功能与实现分离

装饰器模式:在不改变接口的情况下,增加新的功能

标签:学习,String,Iterator,void,适应,Book,bookShelf,设计模式,public
来源: https://www.cnblogs.com/destinyzk/p/16583120.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有