设计模式

设计模式

1. 工厂模式

工厂模式就像一个生产线,它能够创建出不同种类的产品。它的使用场景是当需要创建一些类的对象时,可以将这些类放在工厂中统一管理,通过工厂方法来创建对象。

优点:能够统一管理对象的创建,降低了代码的耦合性,方便扩展和维护。

缺点:需要额外的工厂类来创建对象,增加了代码量。

// 抽象产品类
public abstract class Product {
    public abstract void operation();
}

// 具体产品类
public class ConcreteProductA extends Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductA operation");
    }
}

// 具体产品类
public class ConcreteProductB extends Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductB operation");
    }
}

// 工厂类
public class Factory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                return null;
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Product productA = Factory.createProduct("A");
        Product productB = Factory.createProduct("B");
        productA.operation();
        productB.operation();
    }
}

2. 抽象工厂模式

抽象工厂模式类似于一个工厂的工厂,它可以创建一组相关或者相互依赖的对象。使用场景是当需要创建一组有关联的对象时,可以使用抽象工厂模式。

优点:能够统一创建一组相关或者相互依赖的对象,减少了耦合性。

缺点:扩展新的产品族比较困难。

以下是一个基于 Android 的抽象工厂模式的实现示例:

// 抽象产品类
public abstract class Button {
    public abstract void display();
}

// 具体产品类
public class AndroidButton extends Button {
    @Override
    public void display() {
        System.out.println("Android Button");
    }
}

// 具体产品类
public class IOSButton extends Button {
    @Override
    public void display() {
        System.out.println("iOS Button");
    }
}

// 抽象产品类
public abstract class TextField {
    public abstract void display();
}

// 具体产品类
public class AndroidTextField extends TextField {
    @Override
    public void display() {
        System.out.println("Android TextField");
    }
}

// 具体产品类
public class IOSTextField extends TextField {
    @Override
    public void display() {
        System.out.println("iOS TextField");
    }
}

// 抽象工厂类
public abstract class AbstractFactory {

    public abstract Button createButton();
    public abstract TextField createTextField();
    
}

// 具体工厂类 
public class AndroidFactory extends AbstractFactory { 

	@Override 
	public Button createButton() {
	 return new AndroidButton(); 
	}


	@Override
	public TextField createTextField() {
	    return new AndroidTextField();
	}

}

// 具体工厂类 
public class IOSFactory extends AbstractFactory { 

	@Override 
	public Button createButton() {
	 return new IOSButton(); 
	}

	@Override
	public TextField createTextField() {
	    return new IOSTextField();
	}
}


// 客户端代码
public class Client { 
	public static void main(String\[\] args) { 
		AbstractFactory factory = new AndroidFactory(); 
		Button button = factory.createButton(); 
		TextField textField = factory.createTextField(); 
		button.display(); 
		textField.display(); 
	} 
}

3. 生成器模式

生成器模式就像一位厨师,它可以根据顾客的需求来烹饪出不同的菜品。使用场景是当需要构建复杂对象时,可以使用生成器模式,将对象的构建过程分步骤来完成。

优点:能够分步骤构建对象,便于控制对象的构建过程,易于扩展和维护。

缺点:需要定义多个具体的生成器类,增加了代码量。

// 产品类
public class Meal {
    private String drink;
    private String food;
    private String dessert;

    public void setDrink(String drink) {
        this.drink = drink;
    }

    public void setFood(String food) {
        this.food = food;
    }

    public void setDessert(String dessert) {
        this.dessert = dessert;
    }

    public String getDrink() {
        return drink;
    }

    public String getFood() {
        return food;
    }

    public String getDessert() {
        return dessert;
    }
}

// 抽象生成器类
public abstract class MealBuilder {
    protected Meal meal = new Meal();

    public abstract void buildDrink();

    public abstract void buildFood();

    public abstract void buildDessert();

    public Meal getMeal() {
        return meal;
    }
}

// 具体生成器类
public class MealA extends MealBuilder {
    @Override
    public void buildDrink() {
        meal.setDrink("Coke");
    }

    @Override
    public void buildFood() {
        meal.setFood("Hamburger");
    }

    @Override
    public void buildDessert() {
        meal.setDessert("Ice cream");
    }
}

// 具体生成器类
public class MealB extends MealBuilder {
    @Override
    public void buildDrink() {
        meal.setDrink("Sprite");
    }

    @Override
    public void buildFood() {
        meal.setFood("Pizza");
    }

    @Override
    public void buildDessert() {
        meal.setDessert("Cake");
    }
}

// 指挥者类
public class Waiter {
    private MealBuilder mealBuilder;

    public void setMealBuilder(MealBuilder mealBuilder) {
        this.mealBuilder = mealBuilder;
    }

    public Meal getMeal() {
        mealBuilder.buildDrink();
        mealBuilder.buildFood();
        mealBuilder.buildDessert();
        return mealBuilder.getMeal();

}

// 客户端代码 
public class Client { 
	public static void main(String\[\] args) { 
		Waiter waiter = new Waiter(); 
		MealBuilder mealBuilder = new MealA(); 
		waiter.setMealBuilder(mealBuilder); 
		Meal meal = waiter.getMeal(); 
		System.out.println("Drink: " + meal.getDrink()); 
		System.out.println("Food: " + meal.getFood()); 
		System.out.println("Dessert: " + meal.getDessert()); 
	} 
}


4. 原型模式

原型模式就像复印机,它可以复制出一个完全一样的对象。使用场景是当需要创建一个新对象,但又希望该对象具有某些已有对象的属性时,可以使用原型模式。

优点:可以快速创建一个新对象,而且创建的对象和原型对象完全一样。

缺点:如果原型对象的属性比较复杂,复制起来可能比较耗时。

// 原型接口
public interface Prototype {
    Prototype clone();
}

// 具体原型类
public class AndroidWidget implements Prototype {
    private String type;
    private int size;

    public AndroidWidget(String type, int size) {
        this.type = type;
        this.size = size;
    }

    public String getType() {
        return type;
    }

    public int getSize() {
        return size;
    }

    @Override
    public Prototype clone() {
        return new AndroidWidget(type, size);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AndroidWidget widget1 = new AndroidWidget("Button", 10);
        AndroidWidget widget2 = (AndroidWidget) widget1.clone();
        System.out.println(widget1.getType() + " " + widget1.getSize());
        System.out.println(widget2.getType() + " " + widget2.getSize());
    }
}

5. 单例模式

单例模式就像一个国家的国王,一个国家只有一个国王,而且国王一直存在。使用场景是当需要保证一个类只有一个实例时,可以使用单例模式。

优点:可以保证一个类只有一个实例,避免多个实例造成的资源浪费。

缺点:单例模式可能会造成单例类的职责过重。

// 单例类
public class AndroidManager {
    private static AndroidManager instance;

    private AndroidManager() {
    }

    public static AndroidManager getInstance() {
        if (instance == null) {
            synchronized (AndroidManager.class) {
                if (instance == null) {
                    instance = new AndroidManager();
                }
            }
        }
        return instance;
    }

    public void display() {
        System.out.println("Android Manager is displaying.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AndroidManager manager1 = AndroidManager.getInstance();
        AndroidManager manager2 = AndroidManager.getInstance();
        System.out.println(manager1 == manager2);
        manager1.display();
    }
}

6. 适配器模式

适配器模式就像一个插头转换器,可以将一个插头的形状转换为另一种插头的形状。使用场景是当需要将一个类的接口转换为另一个类的接口时,可以使用适配器模式。

优点:可以让不兼容的接口协同工作。

缺点:适配器模式可能会导致系统中出现过多的适配器类。

// 目标接口
public interface AndroidTarget {
    void play(String fileName);
}

// 适配者类
public class WindowsMediaPlayer {
    public void playFile(String fileName) {
        System.out.println("Playing " + fileName + " using Windows Media Player.");
    }
}

// 适配器类
public class WindowsMediaPlayerAdapter implements AndroidTarget {
    private WindowsMediaPlayer mediaPlayer;

    public WindowsMediaPlayerAdapter(WindowsMediaPlayer mediaPlayer) {
        this.mediaPlayer = mediaPlayer;
    }

    @Override
    public void play(String fileName) {
        mediaPlayer.playFile(fileName);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        WindowsMediaPlayer mediaPlayer = new WindowsMediaPlayer();
        AndroidTarget target = new WindowsMediaPlayerAdapter(mediaPlayer);
        target.play("music.mp3");
    }
}

7. 桥接模式

桥接模式就像一座桥梁,可以连接两个不同的地方。使用场景是当需要将一个类的抽象部分与实现部分分离开来时,可以使用桥接模式。

优点:可以让抽象部分和实现部分独立地变化,从而提高系统的灵活性。

缺点:桥接模式可能会增加系统的复杂度。

// 抽象类
public abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    public abstract void draw();
}

// 具体类
public class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, Color color) {
        super(color);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a " + color.getColor() + " circle at (" + x + ", " + y + ") with radius " + radius);
    }
}

// 接口
public interface Color {
    String getColor();
}

// 实现类
public class RedColor implements Color {
    @Override
    public String getColor() {
        return "red";
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Shape shape = new Circle(10, 20, 30, new RedColor());
        shape.draw();
    }
}

8. 组合模式

组合模式就像一棵树,树由节点和叶子节点组成。使用场景是当需要将一组对象组织成树形结构,并对树中所有对象都进行相同的操作时,可以使用组合模式。

优点:可以使客户端代码简化,将复杂的对象结构简化为树形结构。

缺点:组合模式可能会使设计变得更加抽象。

// 抽象类
public abstract class File {
    private String name;

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

    public String getName() {
        return name;
    }

    public abstract void display();
}

// 叶子节点类
public class TextFile extends File {
    public TextFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("Displaying text file " + getName());
    }
}

// 叶子节点类
public class ImageFile extends File {
    public ImageFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("Displaying image file " + getName());
    }
}

// 叶子节点类
public class VideoFile extends File {
    public VideoFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("Displaying video file " + getName());
    }
}

// 组合节点类
public class Folder extends File {
    private List<File> files;

    public Folder(String name) {
        super(name);
        files = new ArrayList<>();
    }

    public void addFile(File file) {
        files.add(file);
    }

    public void removeFile(File file) {
        files.remove(file);
    }

    @Override
    public void display() {
        System.out.println("Displaying folder " + getName());
        for (File file : files) {
            file.display();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Folder root = new Folder("root");
        Folder folder1 = new Folder("folder1");
        Folder folder2 = new Folder("folder2");
        root.addFile(folder1);
        root.addFile(folder2);
        TextFile textFile1 = new TextFile("textFile1.txt");
        ImageFile imageFile1 = new ImageFile("imageFile1.jpg");
        VideoFile videoFile1 = new VideoFile("videoFile1.mp4");
        folder1.addFile(textFile1);
        folder1.addFile(imageFile1);
        folder2.addFile(videoFile1);
        root.display();
    }
}

9. 装饰模式

装饰模式就像给一个人穿衣服,可以在不改变其本质的情况下,为其添加新的功能。使用场景是当需要动态地给一个对象添加一些额外的职责时,可以使用装饰模式。

优点:可以在不修改原始对象的情况下,动态地给对象添加新的功能。

缺点:装饰模式可能会导致系统中出现过多的装饰器类。

// 抽象类
public abstract class Component {
    public abstract void operation();
}

// 具体类
public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("Performing operation in concrete component.");
    }
}

// 抽象装饰类 
public abstract class Decorator extends Component { 

private Component component;

public Decorator(Component component) {
    this.component = component;
}

@Override
public void operation() {
    if (component != null) {
        component.operation();
    }
}
}

// 具体装饰类 
public class ConcreteDecorator extends Decorator { 
	public ConcreteDecorator(Component component) { 
		super(component); 
	}

	@Override
	public void operation() {
	    super.operation();
	    addBehavior();
	}

	private void addBehavior() {
	    System.out.println("Adding behavior in concrete decorator.");
	}
}

// 客户端代码 
public class Client { 
	public static void main(String\[\] args) { 
		Component component = new ConcreteComponent(); 
		Decorator decorator = new ConcreteDecorator(component); 
		decorator.operation(); 
	} 
}

10. 代理模式

代理模式常常用于一些需要控制访问的对象,例如需要限制客户端直接访问真实对象,可以通过代理对象来进行访问控制。

// 抽象主题
public interface Subject {
    void request();
}

// 真实主题
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Real subject request.");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    @Override
    public void request() {
        beforeRequest();
        realSubject.request();
        afterRequest();
    }

    private void beforeRequest() {
        System.out.println("Before request.");
    }

    private void afterRequest() {
        System.out.println("After request.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Subject subject = new Proxy();
        subject.request();
    }
}

在上述代码中,代理类 Proxy 实现了 Subject 接口,并持有一个真实主题对象 RealSubject 的引用。在 request() 方法中,代理类首先执行了 beforeRequest() 方法,然后调用真实主题对象的 request() 方法,最后执行了 afterRequest() 方法。这样做可以在访问真实主题对象之前或之后进行一些额外的操作,例如权限验证、缓存数据等。

代理模式的优点是可以实现访问控制和日志记录等功能,同时也可以减少系统的耦合度,增加代码的可维护性和扩展性。但代理模式也存在一些缺点,例如会增加代码的复杂度,增加系统的运行开销,同时也可能会降低系统的性能。

11. 责任链模式

责任链模式通常用于处理一些需要多个对象共同处理的请求,例如 Android 中的事件分发机制。下面是一个基于 Android 的责任链模式实现示例:

// 抽象处理器
public abstract class Handler {
    private Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public void handleRequest(int request) {
        if (canHandle(request)) {
            handle(request);
        } else if (successor != null) {
            successor.handleRequest(request);
        } else {
            System.out.println("No handler can handle the request.");
        }
    }

    protected abstract boolean canHandle(int request);

    protected abstract void handle(int request);
}

// 具体处理器
public class ConcreteHandler1 extends Handler {
    @Override
    protected boolean canHandle(int request) {
        return request >= 0 && request < 10;
    }

    @Override
    protected void handle(int request) {
        System.out.println("Handling request in concrete handler 1.");
    }
}

public class ConcreteHandler2 extends Handler {
    @Override
    protected boolean canHandle(int request) {
        return request >= 10 && request < 20;
    }

    @Override
    protected void handle(int request) {
        Log.e("chain", "handle: concreteHandler2 handle");
    }
}

 private void testChain() {
        ConcreteHandler1 concreteHandler1 = new ConcreteHandler1();
        ConcreteHandler2 concreteHandler2 = new ConcreteHandler2();
        concreteHandler1.setSuccessor(concreteHandler2);
        concreteHandler1.handleRequest(10);
    }

在上述代码中,抽象处理器 Handler 定义了一个后继处理器 successor 和一个处理请求的方法 handleRequest(),具体处理器 ConcreteHandler1ConcreteHandler2 继承了抽象处理器并实现了处理请求的方法。在处理请求时,如果当前处理器可以处理请求,则调用其处理请求的方法,否则将请求转发给后继处理器,直到找到可以处理请求的处理器为止。

责任链模式的优点是可以动态地组合处理器,增强系统的灵活性和可扩展性。同时,责任链模式还可以避免请求发送者和接收者之间的耦合关系,提高系统的可维护性和可测试性。但责任链模式也存在一些缺点,例如会增加系统的复杂度和运行开销,同时也可能会降低系统的性能。

12. 命令模式

命令模式通常用于将请求封装成对象,从而使请求参数化、队列化和记录化,以便支持撤销、恢复和事务等操作。

// 命令接口
public interface Command {
    void execute();
}

// 具体命令
public class ConcreteCommand1 implements Command {
    private Receiver receiver;

    public ConcreteCommand1(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.action1();
    }
}

public class ConcreteCommand2 implements Command {
    private Receiver receiver;

    public ConcreteCommand2(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.action2();
    }
}

// 接收者
public class Receiver {
    public void action1() {
        System.out.println("Receiver action 1.");
    }

    public void action2() {
        System.out.println("Receiver action 2.");
    }
}

// 调用者
public class Invoker {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void executeCommand() {
        command.execute();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Command command1 = new ConcreteCommand1(receiver);
        Command command2 = new ConcreteCommand2(receiver);
        Invoker invoker = new Invoker();
        invoker.setCommand(command1);
        invoker.executeCommand();
        invoker.setCommand(command2);
        invoker.executeCommand();
    }
}

在上述代码中,命令接口 Command 定义了一个执行命令的方法 execute(),具体命令 ConcreteCommand1ConcreteCommand2 实现了命令接口并调用了接收者的方法。接收者 Receiver 定义了两个具体的方法 action1()action2(),可以被具体命令调用。调用者 Invoker 持有一个命令对象,并提供了执行命令的方法 `executeCommand

13. 备忘录模式

备忘录模式可以将对象的内部状态封装成备忘录对象,以便后续恢复对象的状态。下面是一个基于 Android 的备忘录模式实现示例:

// 备忘录类
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// 发起者类
public class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}

// 管理者类
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void addMemento(Memento memento) {
        mementoList.add(memento);
    }

    public Memento getMemento(int index) {
        return mementoList.get(index);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("State 1");
        originator.setState("State 2");
        caretaker.addMemento(originator.saveStateToMemento());

        originator.setState("State 3");
        caretaker.addMemento(originator.saveStateToMemento());

        Memento memento1 = caretaker.getMemento(0);
        Memento memento2 = caretaker.getMemento(1);

        originator.getStateFromMemento(memento1);
        System.out.println("Current state: " + originator.getState());

        originator.getStateFromMemento(memento2);
        System.out.println("Current state: " + originator.getState());
    }
}

在上述代码中,备忘录类 Memento 封装了发起者 Originator 的状态。发起者类提供了设置状态和获取状态的方法,并提供了保存状态和恢复状态的方法。管理者类 Caretaker 存储了多个备忘录对象,并提供了获取备忘录对象的方法。在客户端代码中,创建一个发起者对象和一个管理者对象,并对发起者对象的状态进行修改和保存。最后通过管理者对象获取备忘录对象,并使用发起者对象恢复备忘录对象中保存的状态。

备忘录模式的优点是可以将状态信息封装在备忘录对象中,避免了直接访问状态信息的问题,并提高了系统的灵活性和可维护性。同时,备忘录模式还可以实现撤销、恢复和事务等操作。但备忘录模式也存在一些缺点,例如可能会导致系统的性能和内存开销增加,并且需要消耗额外的存储空间来存储备忘录对象。

14. 观察者模式

观察者模式通常用于实现对象之间的观察者模式

观察者模式通常用于实现对象之间的一对多关系,当一个对象的状态发生改变时,会自动通知其它对象进行更新。

// 观察者接口
public interface Observer {
    void update(int value);
}

// 主题接口
public interface Subject {
    void attach(Observer observer);

    void detach(Observer observer);

    void notifyObservers();
}

// 具体主题类
public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;

    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void detach(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

// 具体观察者类
public class ConcreteObserver implements Observer {
    private int state;

    public void update(int value) {
        state = value;
        System.out.println("Observer state updated to: " + state);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        Observer observer1 = new ConcreteObserver();
        Observer observer2 = new ConcreteObserver();

        subject.attach(observer1);
        subject.attach(observer2);

        subject.setState(1);

        subject.detach(observer1);

        subject.setState(2);
    }
}

在上述代码中,主题接口 Subject 定义了注册观察者、移除观察者和通知观察者的方法。具体主题类 ConcreteSubject 实现了主题接口,并维护了观察者列表和状态信息。具体观察者类 ConcreteObserver 实现了观察者接口,并实现了更新状态的方法。在客户端代码中,创建一个具体主题对象和两个具体观察者对象,并将观察者对象注册到主题对象中。随后修改主题对象的状态信息,通知所有观察者进行更新。最后移除一个观察者对象,再次修改主题对象的状态信息,只有一个观察者对象进行更新。

观察者模式的优点是可以实现对象之间的松耦合,同时支持动态添加和删除观察者对象。观察者模式还可以实现广播通知功能,支持一对多和一对一等多种模式。但观察者模式也存在一些缺点,例如可能导致性能问题和内存泄漏问题,并且需要考虑观察者对象的线程安全问题。此外,在使用观察者模式时需要注意避免循环依赖问题。

15. 状态模式

状态模式通常用于处理对象在不同状态下的行为差异问题。状态模式将对象的状态抽象成一个状态类,通过将状态类与主体类进行关联,从而使主体类可以在不同状态下表现出不同的行为。下面是一个基于 Android 的状态模式实现示例:

// 抽象状态类
public abstract class State {
    public abstract void handle(Context context);
}

// 具体状态类A
public class ConcreteStateA extends State {
    public void handle(Context context) {
        System.out.println("State A handling...");
        context.setState(new ConcreteStateB());
    }
}

// 具体状态类B
public class ConcreteStateB extends State {
    public void handle(Context context) {
        System.out.println("State B handling...");
        context.setState(new ConcreteStateA());
    }
}

// 上下文类
public class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        state.handle(this);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());

        context.request();
        context.request();
        context.request();
        context.request();
    }
}

在上述代码中,抽象状态类 State 定义了状态的抽象方法 handle(),具体状态类 ConcreteStateAConcreteStateB 分别实现了 handle() 方法,并在方法中通过 Context 对象调用了 setState() 方法进行状态转换。上下文类 Context 维护了当前的状态信息,并提供了 setState()request() 方法用于状态转换和行为执行。在客户端代码中,创建一个初始状态为 ConcreteStateA 的上下文对象,并多次调用 request() 方法,输出结果表明状态被不断转换,并按照不同的状态执行了不同的行为。

状态模式的优点是可以将状态相关的行为封装到具体状态类中,使得代码更加清晰和易于维护。状态模式还可以避免大量的条件分支语句,提高了代码的可扩展性和可读性。但状态模式也存在一些缺点,例如需要编写大量的状态类和状态转换逻辑,可能导致代码过于复杂。此外,状态模式也可能导致状态对象过多,占用过多的内存空间。

16. 策略模式

策略模式是一种行为型设计模式,用于在运行时选择算法。它允许一个对象在不同的情况下采用不同的算法。策略模式通过将不同的算法封装到具体策略类中,从而使得这些算法可以互相替换。下面是一个基于 Android 的策略模式实现示例:

// 抽象策略类
public interface Strategy {
    void doOperation(int num1, int num2);
}

// 具体策略类A
public class OperationAdd implements Strategy {
    public void doOperation(int num1, int num2) {
        System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
    }
}

// 具体策略类B
public class OperationSubstract implements Strategy {
    public void doOperation(int num1, int num2) {
        System.out.println(num1 + " - " + num2 + " = " + (num1 - num2));
    }
}

// 具体策略类C
public class OperationMultiply implements Strategy {
    public void doOperation(int num1, int num2) {
        System.out.println(num1 + " * " + num2 + " = " + (num1 * num2));
    }
}

// 策略执行类
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy(int num1, int num2) {
        strategy.doOperation(num1, num2);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        context.executeStrategy(10, 5);

        context = new Context(new OperationSubstract());
        context.executeStrategy(10, 5);

        context = new Context(new OperationMultiply());
        context.executeStrategy(10, 5);
    }
}

在上述代码中,抽象策略类 Strategy 定义了算法的抽象方法 doOperation(),具体策略类 OperationAddOperationSubstractOperationMultiply 分别实现了 doOperation() 方法,并提供了不同的算法实现。策略执行类 Context 维护了当前算法的策略对象,并提供了 executeStrategy() 方法用于调用具体策略类的 doOperation() 方法。在客户端代码中,通过创建一个策略执行类的实例,并将不同的具体策略类作为参数传递给策略执行类的构造方法,实现了不同算法的运行时切换。

策略模式的优点在于能够在运行时动态地选择算法,避免了大量的条件分支语句,并且可以很方便地扩展新的算法。策略模式还能够将不同的算法封装到具体策略类中,使得代码更加清晰和易于维

17. 模板方法模式

模板方法模式是一种行为型设计模式,用于定义一个操作中的算法骨架,将一些步骤延迟到子类中实现。这种模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。在 Android 中,模板方法模式通常用于在父类中定义一些公共的操作步骤,而将具体的实现交给子类。下面是一个基于 Android 的模板方法模式实现示例:

// 抽象类
public abstract class Game {
    abstract void initialize();

    abstract void startPlay();

    abstract void endPlay();

    // 模板方法
    public final void play() {

        // 初始化游戏
        initialize();

        // 开始游戏
        startPlay();

        // 结束游戏
        endPlay();
    }
}

// 具体类
public class Cricket extends Game {

    @Override
    void endPlay() {
        System.out.println("Cricket Game Finished!");
    }

    @Override
    void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {

        Game game = new Cricket();
        game.play();
    }
}

在上述代码中,抽象类 Game 定义了游戏的模板方法 play(),其中包含了游戏的初始化、开始和结束三个步骤。具体的游戏类 Cricket 继承了抽象类 Game,并且实现了 initialize()startPlay()endPlay() 这三个步骤的具体实现。在客户端代码中,创建了一个 Cricket 对象,并调用 play() 方法来启动游戏。

模板方法模式的优点在于能够减少代码的重复性,提高代码的复用性,同时还能够实现一种算法的统一管理和控制。此外,模板方法模式还能够使得算法的具体实现与算法的调用分离,使得程序更加灵活和易于维护。

模板方法模式的缺点在于,由于算法的实现由子类来完成,因此可能会导致子类的数量增多,从而增加了代码的维护成本。此外,模板方法模式也可能导致代码的层次结构变得复杂,不易于理解和维护。

18. 访问者模式

访问者模式是一种行为型设计模式,用于将算法从其所操作的对象结构中分离出来,从而可以在不改变对象结构的前提下定义新的操作。这种模式将对象结构和算法分离,从而使得算法可以独立于对象结构而变化。在 Android 中,访问者模式通常用于对复杂对象结构进行遍历或者进行一些统计操作。下面是一个基于 Android 的访问者模式实现示例:

// 抽象访问者
interface Visitor {
    void visit(File file);
    void visit(Directory directory);
}

// 抽象元素类
interface Element {
    void accept(Visitor visitor);
}

// 文件类,具体元素类
class File implements Element {
    private final String name;

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

    public String getName() {
        return name;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 目录类,具体元素类
class Directory implements Element {
    private final List<Element> elements;

    public Directory(List<Element> elements) {
        this.elements = elements;
    }

    public List<Element> getElements() {
        return elements;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体访问者类
class CountVisitor implements Visitor {
    private int fileCount;
    private int directoryCount;

    public void visit(File file) {
        fileCount++;
    }

    public void visit(Directory directory) {
        directoryCount++;
        for (Element element : directory.getElements()) {
            element.accept(this);
        }
    }

    public int getFileCount() {
        return fileCount;
    }

    public int getDirectoryCount() {
        return directoryCount;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        List<Element> elements = new ArrayList<>();
        elements.add(new File("file1"));
        elements.add(new File("file2"));
        elements.add(new Directory(Arrays.asList(
                new File("file3"),
                new File("file4"),
                new Directory(Collections.singletonList(new File("file5")))
        )));

        Directory rootDirectory = new Directory(elements);
        CountVisitor visitor = new CountVisitor();
        rootDirectory.accept(visitor);

        System.out.println("File count: " + visitor.getFileCount());
        System.out.println("Directory count: " + visitor.getDirectoryCount());
    }
}

在上述代码中,抽象元素类 Element 定义了 accept() 方法,用于接受访问者的访问。具体元素类 FileDirectory 实现了 Element 接口,并且在 accept() 方法中调用了访问者的 visit() 方法。抽象访问者接口 Visitor 定义了 visit() 方法,具体访问者类 CountVisitor 实现了 Visitor 接口,并且在 visit() 方法中对元素进行统计。在客户端代码中,创建了一个复杂的对象结构,即一个目录中包含了多个文件和子目录。然后创建了一个 CountVisitor 对象。

代码示例

posted @ 2023-04-12 16:26  懒懒初阳  阅读(20)  评论(0编辑  收藏  举报