设计模式

Posted 懒懒初阳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式相关的知识,希望对你有一定的参考价值。

设计模式

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.get



// 客户端代码 
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)

在上述代码中,抽象处理器 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 对象。

研磨设计模式

第1章 设计模式基础

  1.1 设计模式是什么

    1.1.1 什么是模式

    1.1.2 设计模式的概念

    1.1.3 设计模式的理解

    1.1.4 设计模式的历史

  1.2 设计模式有什么

    1.2.1 设计模式的组成

    1.2.2 设计模式的分类

  1.3 设计模式的学习

    1.3.1 为什么要学习设计模式

    1.3.2 学习设计模式的层次

    1.3.3 如何学习设计模式

  1.4 本书的组织方式

    1.4.1 本书所讲述的设计模式的提纲

    1.4.2 每个模式的讲述结构

第2章 简单工厂

  2.1 场景问题

    2.1.1 接口回顾

    2.1.2 面向接口编程

    2.1.3 不用模式的解决方案

    2.1.4 有何问题

  2.2 场景问题

    2.2.1 使用简单工厂来解决问题

    2.2.2 简单工厂的结构和说明

    2.2.3 简单工厂示例代码

    2.2.4 使用简单工厂重写示例

  2.3 模式讲解

    2.3.1 典型疑问

    2.3.2 认识简单工厂

    2.3.3 简单工厂中方法的写法

    2.3.4 可配置的简单工厂

    2.3.5 简单工厂的优缺点

    2.3.6 思考简单工厂

    2.3.7 相关模式

第3章 外观模式(Facade)

  3.1 场景问题

    3.1.1 生活中的示例

    3.1.2 代码生成的应用

    3.1.3 不用模式的解决方案

    3.1.4 有何问题

  3.2 解决方案

    3.2.1 使用外观模式来解决问题

    3.2.2 外观模式的结构和说明

    3.2.3 外观模式示例代码

    3.2.4 使用外观模式重写示例

  3.3 模式讲解

    3.3.1 认识外观模式

    3.3.2 外观模式的实现

    3.3.3 外观模式的优缺点

    3.3.4 思考外观模式

    3.3.5 相关模式

第4章 适配器模式(Adapter)

  4.1 场景问题

    4.1.1 装配电脑的例子

    4.1.2 同时支持数据库和文件的日志管理

    4.1.3 有何问题

  4.2 解决方案

    4.2.1 使适配器模式来解决问题

    4.2.2 适配器模式的结构和说明

    4.2.3 适配器模式示例代码

    4.2.4 使用适配器模式来实现示例

  4.3 模式讲解

    4.3.1 认识适配器模式

    4.3.2 适配器模式的实现

    4.3.3 双向适配器

    4.3.4 对象适配器和类适配器

    4.3.5 适配器模式的优缺点

    4.3.6 思考适配器模式

    4.3.7 相关模式

第5章 单例模式(Singleton)

  5.1 场景问题

    5.1.1 读取配置文件的内容

    5.1.2 不用模式的解决方案

    5.1.3 有何问题

  5.2 解决方案

    5.2.1 使用单例模式来解决问题

    5.2.2 单例模式的结构和说明

    5.2.3 单例模式示例代码

    5.2.4 使用单例模式重写示例

  5.3 模式讲解

    5.3.1 认识单例模式

    5.3.2 懒汉式和饿汉式实现

    5.3.3 延迟加载的思想

    5.3.4 缓存的思想

    5.3.5 Java中缓存的基本实现

    5.3.6 利用缓存来实现单例模式

    5.3.7 单例模式的优缺点

    5.3.8 在Java中一种更好的单例实现方式

    5.3.9 单例和枚举

    5.3.10 思考单例模式

    5.3.11 相关模式

第6章 工厂方法模式(Factory Method)

  6.1 场景问题

    6.1.1 导出数据的应用框架

    6.1.2 框架的基础知识

    6.1.3 有何问题

  6.2 解决方案

    6.2.1 使用工厂方法模式来解决问题

    6.2.2 工厂方法模式的结构和说明

    6.2.3 工厂方法模式示例代码

    6.2.4 使用工厂方法模式来实现示例

  6.3 模式讲解

    6.3.1 认识工厂方法模式

    6.3.2 工厂方法模式与IoC/DI

    6.3.3 平行的类层次结构

    6.3.4 参数化工厂方法

    6.3.5 工厂方法模式的优缺点

    6.3.6 思考工厂方法模式

    6.3.7 相关模式

第7章 抽象工厂模式(Abstract Factory)

  7.1 场景问题

    7.1.1 选择组装电脑的配件

    7.1.2 不用模式的解决方案

    7.1.3 有何问题

  7.2 解决方案

    7.2.1 使用抽象工厂模式来解决问题

    7.2.2 抽象工厂模式的结构和说明

    7.2.3 抽象工厂模式示例代码

    7.2.4 使用抽象工厂模式重写示例

  7.3 模式讲解

    7.3.1 认识抽象工厂模式

    7.3.2 定义可扩展的工厂

    7.3.3 抽象工厂模式和DAO

    7.3.4 抽象工厂模式的优缺点

    7.3.5 思考抽象工厂模式

    7.3.6 相关模式

第8章 生成器模式(Builder)

  8.1 场景问题

    8.1.1 继续导出数据的应用框架

    8.1.2 不用模式的解决方案

    8.1.3 有何问题

  8.2 解决方案

    8.2.1 使用生成器模式来解决问题

    8.2.2 生成器模式的结构和说明

    8.2.3 生成器模式示例代码

    8.2.4 使用生成器模式重写示例

  8.3 模式讲解

    8.3.1 认识生成器模式

    8.3.2 生成器模式的实现

    8.3.3 使用生成器模式构建复杂对象

    8.3.4 生成器模式的优点

    8.3.5 思考生成器模式

    8.3.6 相关模式

第9章 原型模式(Prototype)

  9.1 场景问题

    9.1.1 订单处理系统

    9.1.2 不用模式的解决方案

    9.1.3 有何问题

  9.2 解决方案

    9.2.1 使用原型模式来解决问题

    9.2.2 原型模式的结构和说明

    9.2.3 原型模式示例代码

    9.2.4 使用原型模式重写示例

  9.3 模式讲解

    9.3.1 认识原型模式

    9.3.2 Java中的克隆方法

    9.3.3 浅度克隆和深度克隆

    9.3.4 原型管理器

    9.3.5 原型模式的优缺点

    9.3.6 思考原型模式

    9.3.7 相关模式

第10章 中介者模式(Mediator)

  10.1 场景问题

    10.1.1 如果没有主板

    10.1.2 有何问题

    10.1.3 使用电脑来看电影

  10.2 解决方案

    10.2.1 使用中介者模式来解决问题

    10.2.2 中介者模式的结构和说明

    10.2.3 中介者模式示例代码

    10.2.4 使用中介者模式来实现示例

  10.3 模式讲解

    10.3.1 认识中介者模式

    10.3.2 广义中介者

    10.3.3 中介者模式的优缺点

    10.3.4 思考中介者模式

    10.3.5 相关模式

第11章 代理模式(Proxy)

  11.1 场景问题

    11.1.1 访问多条数据

    11.1.2 不用模式的解决方案

    11.1.3 有何问题

  11.2 解决方案

    11.2.1 使用代理模式来解决问题

    11.2.2 代理模式的结构和说明

    11.2.3 代理模式示例代码

    11.2.4 使用代理模式重写示例

  11.3 模式讲解

    11.3.1 认识代理模式

    11.3.2 保护代理

    11.3.3 Java中的代理

    11.3.4 代理模式的特点

    11.3.5 思考代理模式

    11.3.6 相关模式

第12章 观察者模式(Observer)

  12.1 场景问题

    12.1.1 订阅报纸的过程

    12.1.2 订阅报纸的问题

  12.2 解决方案

    12.2.1 使用观察者模式来解决问题

    12.2.2 观察者模式的结构和说明

    12.2.3 观察者模式示例代码

    12.2.4 使用观察者模式实现示例

  12.3 模式讲解

    12.3.1 认识观察者模式

    12.3.2 推模式和拉模型

    12.3.3 Java中的观察者模式

    12.3.4 观察者模式的优缺点

    12.3.5 思考观察者模式

    12.3.6 Swing中的观察者

    12.3.7 简单变形示例-区别对待观察者

    12.3.8 相关模式

第13章 命令模式(Command)

  13.1 场景问题

    13.1.1 如何开机

    13.1.2 与我何干

    13.1.3 有何问题

  13.2 解决方案

    13.2.1 使用命令模式来解决问题

    13.2.2 命令模式的结构和说明

    13.2.3 命令模式示例代码

    13.2.4 使用命令模式l来实现示例

  13.3 模式讲解

    13.3.1 认识命令模式

    13.3.2 参数化配置

    13.3.3 可撤销的操作

    13.3.4 宏命令

    13.3.5 队列请求

    13.3.6 日志请求

    13.3.7 命令模式的优点

    13.3.8 思考命令模式

    13.3.9 退化的命令模式

    13.3.10 相关模式

第14章 迭代器模式(Iterator)

  14.1 场景问题

    14.1.1 工资表数据的集合

    14.1.2 有何问题

  14.2 解决方案

    14.2.1 使用迭代器模式解决问题

    14.2.2 迭代器模式的结构和说明

    14.2.3 迭代器模式示例代码

    14.2.4 使用迭代器模式来实现示例

  14.3 模式讲解

    14.3.1 认识迭代器模式

    14.3.2 使用Java的迭代器

    14.3.3 带迭代策略的迭代器

    14.3.4 双向迭代器

    14.3.5 迭代器模式的有点

    14.3.6 思考迭代器模式

    14.3.7 翻页迭代

    14.3.8 相关模式

第15章 组合模式(Composite)

  15.1 场景问题

    15.1.1 商品类别树

    15.1.2 不用模式的解决方案

    15.1.3 有何问题

  15.2 解决方案

    15.2.1 使用组合模式来解决问题

    15.2.2 组合模式的结构和说明

    15.2.3 组合模式示例代码

    15.2.4 使用组合模式重写示例

  15.3 模式讲解

    15.3.1 认识组合模式

    15.3.2 安全性和透明性

    15.3.3 父组件引用

    15.3.4 环状引用

    15.3.5 组合模式的优缺点

    15.3.6 思考组合模式

    15.3.7 相关模式

第16章 模板方法模式(Template Method)

  16.1 场景问题

    16.1.1 登录控制

    16.1.2 不用模式的解决方案

    16.1.3 有何问题

  16.2. 解决方案

    16.2.1 使用模板方法模式来解决问题

    16.2.2 模板方法模式的结构和说明

    16.2.3 模板方法模式示例代码

    16.2.4 使用模板方法模式重写示例

  16.3 模式讲解

    16.3.1 认识模板方法模式

    16.3.2 模板的写法

    16.3.3 Java回调与模板方法模式

    16.3.4 典型应用:排序

    16.3.5 实现通用的增删改查

    16.3.6 模板方法模式的优缺点

    16.3.7 思考模板方法模式

    16.3.8 相关模式

第17章 策略模式(Strategy)

  17.1 场景问题

    17.1.1 报价管理

    17.1.2 不用模式的解决方案

    17.1.3 有何问题

  17.2 解决方案

    17.2.1 使用策略模式来解决问题

    17.2.2 策略模式的结构和说明

    17.2.3 策略模式示例代码

    17.2.4 使用策略模式重写示例

  17.3 模式讲解

    17.3.1 认识策略模式

    17.3.2 Context和Strategy的关系

    17.3.3 

以上是关于设计模式的主要内容,如果未能解决你的问题,请参考以下文章

C#设计模式--桥接模式

23种设计模式总结

iOS中都有啥设计模式?各个设计模式的作用

86 设计模式23种设计模式概述

设计模式概述(23种设计模式目录)

设计模式