由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

设计模式—模板方法模式

JAVA 西门飞冰 6289℃
[隐藏]

1.定义

模板⽅法模式(Template Method)是⼀种⾏为设计模式, 它在超类中定义了⼀个算法的框架, 允许⼦类在不修改结构的情况下重写算法的特定步骤。

基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改

2.代码结构

image-20221003113807704

3.代码示例

需求:写了一个机器人可以向指定的网站发送消息

抽象类:规定流程是怎么做的

public abstract class Network {
    String userName;
    String password;

    Network() {}

    // 将数据发布到网络
    public boolean post(String message) {
        // 发布消息前的身份验证,每个网站使用不同的身份验证方法
        if (logIn(this.userName, this.password)) {
            // 发送消息
            boolean result =  sendData(message.getBytes());
            // 退出登陆
            logOut();
            return result;
        }
        return false;
    }

    abstract boolean logIn(String userName, String password);
    abstract boolean sendData(byte[] data);
    abstract void logOut();
}

向Twitter发送消息具体类:

public class Twitter extends Network {

    public Twitter(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    @Override
    public boolean logIn(String userName, String password) {
        System.out.println("\n正在检查用户名和密码");
        System.out.println("用户名: " + this.userName);
        System.out.print("密码: ");
        for (int i = 0; i < this.password.length(); i++) {
            System.out.print("*");
        }
        simulateNetworkLatency();
        System.out.println("\n\n成功登陆");
        return true;
    }

    @Override
    public boolean sendData(byte[] data) {
        boolean messagePosted = true;
        if (messagePosted) {
            System.out.println("消息: '" + new String(data) + "' 已经发布到 Twitter 上");
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void logOut() {
        System.out.println("用户: '" + userName + "'已经从Twitter 退出");
    }

    private void simulateNetworkLatency() {
        try {
            int i = 0;
            System.out.println();
            while (i < 10) {
                System.out.print(".");
                Thread.sleep(500);
                i++;
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

向Facebook发送消息具体类:

public class Facebook extends Network {
    public Facebook(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    @Override
    public boolean logIn(String userName, String password) {
        System.out.println("\n正在检查用户名和密码");
        System.out.println("用户名: " + this.userName);
        System.out.print("密码: ");
        for (int i = 0; i < this.password.length(); i++) {
            System.out.print("*");
        }
        simulateNetworkLatency();
        System.out.println("\n\n 成功登陆 Facebook");
        return true;
    }

    @Override
    public boolean sendData(byte[] data) {
        boolean messagePosted = true;
        if (messagePosted) {
            System.out.println("消息: '" + new String(data) + "' 已经发布到 Facebook 上");
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void logOut() {
        System.out.println("用户: '" + userName + "' 已经从Facebook 退出");
    }

    private void simulateNetworkLatency() {
        try {
            int i = 0;
            System.out.println();
            while (i < 10) {
                System.out.print(".");
                Thread.sleep(500);
                i++;
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

客户端:

public class Client {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        Network network = null;
        System.out.print("请输入用户名: ");
        String userName = reader.readLine();
        System.out.print("请输入密码: ");
        String password = reader.readLine();

        // Enter the message.
        System.out.print("请输入内容: ");
        String message = reader.readLine();

        System.out.println("\n请选择发布消息的社交平台\n" +
                "1 - Facebook\n" +
                "2 - Twitter");
        int choice = Integer.parseInt(reader.readLine());

        // 根据用户选择的不同登陆相应的网站发送消息
        if (choice == 1) {
            network = new Facebook(userName, password);
        } else if (choice == 2) {
            network = new Twitter(userName, password);
        }
        network.post(message);
    }
}

输出内容:

请输入用户名: zhangsan
请输入密码: lisi
请输入内容: 我爱中国共产党

请选择发布消息的社交平台
1 - Facebook
2 - Twitter
2

正在检查用户名和密码
用户名: zhangsan
密码: ****
..........

成功登陆
消息: '我爱中国共产党' 已经发布到 Twitter 上
用户: 'zhangsan'已经从Twitter 退出

4.优点

你可仅允许客户端重写⼀个⼤型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减⼩。

你可将重复代码提取到⼀个超类中。

5.缺点

部分客户端可能会受到算法框架的限制。

通过⼦类抑制默认步骤实现可能会导致违反⾥⽒替换原则。

每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大

6.使用场景

当你只希望客户端扩展某个特定算法步骤, ⽽不是整个算法或其结构时, 可使⽤模板⽅法模式。

当多个类的算法除⼀些细微不同之外⼏乎完全⼀样时, 你可使⽤该模式。 但其后果就是, 只要算法发⽣变化, 你就可能需要修改所有的类。

转载请注明:西门飞冰的博客 » 设计模式—模板方法模式

喜欢 (0)or分享 (0)