面向对象设计模式

一、创建型设计模式

创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。

1.1 单例(Singleton)

类和它们的实例间通常是一对多的关系,但存在如操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、系统中的缓存等,需要被设计成同个应用中仅能存在一个实例。

class EagerSingleton {
    private static EagerSingleton instance = new EagerSingleton();

    private EagerSingleton(){}
    
    public static EagerSingleton getInstance() {
        return instance;
    }
    
 }

class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

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

}

1.2 原型(Prototype)

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象;这种方式创建对象非常高效,根本无须知道对象创建的细节。

  • 克隆与复制
  1. 浅克隆:通过 prototype.clone() 创建一个新对象,新对象的属性和原有对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  2. 深克隆:通过 prototype.clone() 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
  3. 复制:通过 new SomeObj() 创建一个新对象,然后将原有对象的所有属性拷贝到新对象中。
  • 浅克隆
@Data
public class Teacher implements Cloneable {
    private String name;
    private int age;

    @Override public Teacher clone() throws CloneNotSupportedException {
        return (Teacher) super.clone();
    }
}
  • 深克隆
@Data
public class Student implements Cloneable {
    private String name;
    private int age;
    private Teacher teacher;

    @Override public Student clone() throws CloneNotSupportedException {
        Student s = (Student) super.clone();
        Teacher t = this.teacher.clone();
        s.setTeacher(t);
        return s;
    }
}
  • 复制
public class DesignPatternTest {
    @Test public void testPrototype() {
        Teacher t1 = new Teacher();
        t1.setName("Ross");
        t1.setAge(37);

        Teacher t2 = new Teacher();
        t2.setName(t1.getName());
        t2.setAge(t1.getAge());
    }
}

@Data
class Teacher {
    private String name;
    private int age;
}
  • 克隆的缺点
  1. 需要为每一个类都配置一个 clone 方法,存在违背了开闭原则的隐患。
  2. 对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆。
  • 总结
  1. 通常情况下,使用复制来完成原型模式的设计,如 Spring 的 @Scope("prototype")、JPA 的 POJO 都是先创建出对象,然后为属性赋值。
  2. 深克隆的使用场景:保存对象某一时刻的完整状态,用于后续的恢复。
  • 辅助实现克隆与复制效果的工具包
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>
  1. 浅克隆
// hutool 代价是牺牲了继承其它类的能力
private static class Dog extends CloneSupport<Dog>{
    private String name = "wangwang";
    private int age = 3;
}
  1. 深克隆
// hutool
ObjectUtil.cloneByStream(obj);

// lang3
SerializationUtils.clone(user);
  1. 复制
// SpringBoot
SomeObj o1 = new SomeObj(/* some properties */);
SomeObj o1 = new SomeObj();
BeanUtils.copyProperties(o1, o2);

1.3 工厂(Factory)

任何一行使用了 new 关键字的代码都违反了依赖倒置原则。

1.3.1 简单工厂

用于引出工厂的概念,生产中缺点较多不建议使用(职责过重、违背高聚合原则 …)。

public class DesignPatternTest {
    @Test public void testSimpleFactory() {
        Phone mi = PhoneFactory.getNewInstance(PhoneType.MI);
        Phone huawei = PhoneFactory.getNewInstance(PhoneType.HUAWEI);
        mi.call("110"); // Calling from mi : 110
        huawei.call("120"); // Calling from Huawei : 120
    }
}

class PhoneFactory {
    public static Phone getNewInstance(PhoneType phoneType) {
        switch(phoneType) {
            case MI: return new Mi();
            case HUAWEI: return new Huawei();
            default: throw new RuntimeException("Should never enter here!");
        }
    }
}

enum PhoneType {
    MI, HUAWEI;
}

interface Phone {
    void call(String no);
}

class Mi implements Phone {
    @Override public void call(String no) {
        System.out.println("Calling from mi : " + no);
    }
}

class Huawei implements Phone {
    @Override public void call(String no) {
        System.out.println("Calling from Huawei : " + no);
    }
}

1.3.2 工厂方法

对象拥有各自的工厂方法类,新增对象不会破坏已有类的封装性,但存在类数量倍增的问题。

图片引自 怪咖软妹@Java设计模式——工厂模式,很棒的博主!

在这里插入图片描述

1.3.3 抽象工厂

解决了工厂方法中类数量倍增的缺点,同时产生另一个问题:当某个工厂需要新增品类时,所有工厂必须做出回应,或通过 > Java 8 的接口默认实现能力来处理。

在这里插入图片描述

1.4 建造者(Builder)

参考:《Design Patterns - Elements of Reusable Object Oriented Software》3.2 Builder

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

  • Applicability
  1. the algorithm for creating a complex object should be independent of the parts that make up the object and how thry’re assembled.
  2. the construction process must allow different representations for the object that’s constucted.
  • Structure
    在这里插入图片描述
  1. Builder:specifies an abstract interface for creating parts of a Product object.
  2. ConcreteBuilder:constructs and assembles parts of the product by implementing the Builder interface; defines and keeps track of the representation it creates; provides an interface for retrieving the product.
  3. Director:constructs an object using the Builder interface.
  4. Product: represents the complex object under construction, ConcreteBuidler builds the product’s internal representation and defines the process by which it’s asssembled; includes classes that define the constituent(组成的) parts, including interfaces for assembling the parts into the final result.
    在这里插入图片描述
  • 举例:RTFReader 用于将富文本解析成各种格式的文档如 ASCIIText、TeXText、TextWidget

在这里插入图片描述

  • 优点
  1. vary product’s internal representation
  2. isolate code for construction and representation
  3. finer control over the construction process

二、结构型设计模式

结构型模式:用于描述如何将类或对象按某种布局组成更大的结构。

2.1 代理(Proxy)

访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

在这里插入图片描述

2.1.1 静态代理

将原对象的行为进行再次封装,通常是对原有逻辑的增强。

public class ProxyTest {
    public static void main(String[] args) {
        Subject proxy = new Proxy(new RealSubject());
        proxy.request();
    }
}

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

// 真实主题
class RealSubject implements Subject {
    public void request() { System.out.println("访问真实主题方法..."); }
}

// 代理
class Proxy implements Subject {
    private Subject subject;

	public Proxy(Subject subject) { this.subject = subject; }

    public void request() {
        preRequest(); subject.request(); postRequest();
    }

    public void preRequest() { System.out.println("访问真实主题之前的预处理。"); }
    public void postRequest() { System.out.println("访问真实主题之后的后续处理。"); }
}

2.1.2 动态代理

运用反射机制动态创建而成,只能对实现了接口的类生成代理,而不能针对类。

    @Test
    public void testDynamicProxy() {
	    Map mapProxyInstance = (Map) Proxy.newProxyInstance(
	                                    DynamicProxyTest.class.getClassLoader(),
	                                    new Class[] { Map.class }, 
	                                    new TimingDynamicInvocationHandler(new HashMap<>()));
	    mapProxyInstance.put("Hello", "World");
	
	    CharSequence csProxyInstance = (CharSequence) Proxy.newProxyInstance(
	                                    DynamicProxyTest.class.getClassLoader(), 
	                                    new Class[] { CharSequence.class }, 
	                                    new TimingDynamicInvocationHandler("Hello World"));
	    csProxyInstance.length();
    }

    // 计算方法运行时长的动态处理器(简单的话可以写成 Lambda)
    class TimingDynamicInvocationHandler implements InvocationHandler {
        private static Logger LOGGER = LoggerFactory.getLogger(TimingDynamicInvocationHandler.class);
        private Object target;

        public TimingDynamicInvocationHandler(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            long start = System.nanoTime();
            Object result = method.invoke(target, args);
            long elapsed = System.nanoTime() - start;
            LOGGER.info("Executing {} finished in {} ns", method.getName(), elapsed);
            return result;
        }
    }

2.1.3 cglib

对指定的类生成一个子类,覆盖其中的方法,final 类或方法是无法继承的。

	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
	</dependency>
	Producer cglibProducer= (Producer) Enhancer.create(Producer.class,
	    new MethodInterceptor() {
	        /**
	         * @param obj    被代理对象
	         * @param method 当前执行的方法
	         * @param args   当前执行方法所需的参数
	         * @param proxy  当前执行方法的代理对象
	         */
	        @Override
	        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
	            Float money = (Float) args[0];
	            if("saleProduct".equals(method.getName())) {
	               return proxy.invoke(obj, money * 0.8f);
	            }
	            return proxy.invoke(obj, money);
	        }
	    });
	cglibProducer.saleProduct(100.0f);

2.2 适配器(Adapter)

在这里插入图片描述

  • 类适配器:uses multiple inheritance to adapt one interface to another

在这里插入图片描述

class ClassAdapter extends Adaptee implements Target
{
    public void request() {
        super.specificRequest();
    }
    
    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request();
    }
}
  • 对象适配器:relies on object composition
class ObjectAdapter implements Target
{
    private Adaptee adaptee;
    
    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    public void request() {
        adaptee.specificRequest();
    }
    
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new ObjectAdapter(adaptee);
        target.request();
    }
}

2.3 桥接(Bridge)

  • 问题引出:Both the abstractions and their implementations want to be extensible by subclassing.

在这里插入图片描述

  • 问题解决:Decouple an abstraction from its implementation so that the two can vary independently.
    在这里插入图片描述

  • Structure

在这里插入图片描述

  1. Abstraction(Window):defines the abstraction’s interface and maintains a reference to an object of type Implementor.
  2. RefinedAbstraction(IconWindow):extends the interface defined by Abstraction.
  3. Implementor(WindowImp):defines the interface for implementation classes. Typically the Implementor interface provides only primitive operations and Abstraction defines higher-level operations based on these primitives.
  4. ConcreteImplementor(XWindowImp):implements the Implementor interface and defines its concrete implementation.

2.4 装饰者(Decorator)

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

  • Structure
    在这里插入图片描述

  • Participants

  1. Component:defines the interface for objects that can have responsibilities added to them dynamically.
  2. ConcreteComponent:defines an object to which additional responsibilities cna be attached.
  3. Decorator:maintains a reference to a Component object and defines an interface that conforms to Component’s interface.
  4. ConcreteDecorator:adds responsibilities to the component.
  • Example:来一杯快乐咖啡吧!

目前提供 HouseBlend、DarkRoast、Espresso 和 Decaf四种口味的咖啡,还可以添加 Milk、Mocha、Soy、Whip四种配料哦!

在这里插入图片描述

public abstract class Beverage {
    private String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

// 必须让 CondimentDecorator能够取代 Beverage
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

public class Espresso extends Beverage {
    public Espresso() {
        super.description = "Espresso";
    }

    public double cost() {
        return 1.99;
    }
}

public class Mocha extends CondimentDecorator {
    private Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    public double cost() {
        return .20 + beverage.cost();
    }
}

public class AsHomeCoffee {
    public static void main(String args[]) {
        Beverage espresso = new Espresso();
        Beverage espressoWithMocha = new Mocha(espresso);
        Beverage espressoWithMochaAndSoy = new Soy(espressoWithMocha);
        espressoWithMochaAndSoy.cost(); // 1.99 + .20 + .xx
        espressoWithMochaAndSoy.getDescription(); // Espresso, Mocha, Soy
    }
}

2.5 外观

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

在这里插入图片描述

  • Participants
  1. Facade:knows which subsystem classes are responsible for a request, delegates client requests to appropriate subsystem objects.
  2. subsystem classes:implement subsystem functionality, handle work assigned by the Facade object, have no knowledge of the facade (that is, they keep no references to it).

2.6 享元(Flyweight)

Using sharing to support large numbers of fine-grained objects efficiently.

在这里插入图片描述

  1. A flyweight is a shared object which may include some unmodifiable intrinsic states that can be used in multiple contexts simultaneously. (characters)
  2. The flyweight accepts extrinisc states which will make operations distinguishable from one to another. (row wrapper and character’s position in row)
  3. Client objects are responsible for passing extrinsic states to the flyweight when it needs it. (renderer)
  • Structure
    在这里插入图片描述
  1. Flyweight:declares an interface through which flyweights can receive and act on extrinsic state.
  2. ConcreteFlyweight:implements the Flyweight interface and adds storage for intrinsic state if any.
  3. UnsharedConcreteFlyweight:not all Flyweight subclasses need to be shared. It’s common for UnsharedConcreteFlyweight objects to have ConcreteFlyweight objects as children.
  4. FlyweightFactory:creates and manages flyweight objects; ensures that flyweights are shared properly. When a client requests a flyweight, the FlyweightFactory object supplies an existing instance or creates one if none exists.
  5. Client:maintains a reference to flyweight(s), computes or stores the extrinsic state of flyweight(s).

2.7 组合(Component)

Compose objects into tree structures to repsent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

  • Structure

在这里插入图片描述

  1. Component:declares the interface for objects in the composition. implements default behavior for the interface common to all classes, as appropriate. declares an interface for accessing and managing its child components. (optional) defines an interface for accessing a component’s parent in the recursive structure, and implements it if that’s appropriate.
  2. Leaf:represents leaf objects in the composition. A leaf has no children. defines behavior for primitive objects in the compoistion.
  3. Composite:defines behavior for components having children. store child components. implements child-related operations in the Component interface.
  4. Client:manipulates objects in the composition through the Component interface.

三、行为型设计模式

用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。

3.1 职责链(Chain of Responsibility)

Avoid coupling the sender of the request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

  • Structure

在这里插入图片描述

  1. Handler:defines an interface for handling requests. (optional) implements the successor link.
  2. ConcreteHandler:handle the requests it is responsible for. can access its accessor. if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor.
  3. Client:initiates the request to a ConcreteHandler objects on the chain.

3.2 命令(Command)

Encapsulate a request as an object, thereby letting you parmeterlize clients with different requests, queue or log requests, and support undoable operations.

  • Structure

在这里插入图片描述

  1. Command:declares an interface for executing an operation.
  2. ConcreteCommand(LightOnCommand、StereoOffCommand):defines a binding between a Receiver object and an action. implements Execute by invoking the corresponding operation(s) on Receiver.
  3. Client(RemoteLoader):creates a ConcreteCommand object and sets its receiver.
  4. Invoker(RemoteControll):asks the command to carry out the request.
  5. Receiver(Light、Stereo):knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.
  • Exmaple:将 动作的请求者动作的执行者 对象中解耦。
    在这里插入图片描述
    在这里插入图片描述
public class RemoteLoader {
	public RemoteControl load() {
		RemoteControl remoteControl = new RemoteControl();

		// 实体装置
		Light livingRoomLight = new Light("Living Room");
		Light kitchenLight = new Light("Kitchen");
		CeilingFan ceilingFan = new CeilingFan("Living Room");
		GarageDoor garageDoor = new GarageDoor("");
		Stereo stereo = new Stereo("Living Room");

		// 封装的命令
		Command livingRoomLightOn = new LightOnCommand(livingRoomLight);
		Command livingRoomLightOff = new LightOffCommand(livingRoomLight);
		Command kitchenLightOn = new LightOnCommand(kitchenLight);
		Command kitchenLightOff = new LightOffCommand(kitchenLight);
		Command ceilingFanOn = new CeilingFanOnCommand(ceilingFan);
		Command ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
		...

		// 装配
		remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
		remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
		remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff);
		...
	}
}

public class RemoteControl {
	private Command[] onCommands;
	private Command[] offCommands;
	private Deque<Command> undoCommands;

	public RemoteControl() {
		onCommands = new Command[7];
		offCommands = new Command[7];
		undoCommands = new LinkedList<>();

		Command noCommand = new NoCommand();
		for (int i = 0; i < 7; i++) {
			onCommands[i] = noCommand;
			offCommands[i] = offCommands;
		}
	}


	public void setCommand(int slot, Command onCommand, Command offCommand) {
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}

	public void onButtonWasPushed(int slot) {
		onCommands[slot].execute();
		recordHistoryCommands(onCommands[slot]);
	}

	public void offButtonWasPushed(int slot) {
		offCommands[slot].execute();
		recordHistoryCommands(offCommands[slot]);
	}

	public void undoButtonWasPushed() {
		Command command = undoCommands.pollFirst();
		if (command != null) {
			command.undo();
		}
	}

	private void recordHistoryCommands(Command command) {
		if (undoCommands.size > 10) {
			undoCommands.pollLast();
		}
		undoCommands.offerFirst(command);
	}

}

public interface Command {
	void execute();
	void undo();
}

public class NoCommand implements Command {
	public void execute() {}
	public void undo() {}
}

public class LightOnCommand implements Command {
	private Light light;

	public LightOnCommand(Light light) {
		this.light = light;
	}

	public void execute() {
		light.on();
	}

	public void undo() {
		light.off();
	}
}

public class StereoOnWithCDCommand implements Command {
	private Stereo stereo;

	public StereoOnWithCDCommand(Stereo stereo) {
		this.stereo = stereo;
	}

	public void execute() {
		stereo.on();
		stereo.setCD();
		stereo.setVolumn(1);
	}

	public void undo() {
		stereo.off();
	}

}

3.3 解释器(Interpretor)

Given a language, define a representation for its grammer along with an interpreter that uses the representation to interpret sentences in the language.

  • Structure
    在这里插入图片描述
  1. AbstractExpression:declares an abstract Interpret operation that is common to all nodes in the abstract syntax tree.
  2. TerminalExpression:implements an Interpret operation associated with terminal symbols in the grammar. an instance is required for every terminal symbol in a sentence.
  3. NonterminalExpression:one such class is required for every rule R:: = R1R2…Rn in the grammar. maintains instance variables of type AbstractExpression for each of the symbol R1 through Rn. implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the variables representing R1 through Rn.
  4. Context:contains information that’s global to the interpreter.
  5. Client:builds (or is given) an abstract syntax tree representing a particular sentence in the language that the grammar defines. The abstract syntax tree is assembled from instances of the NonterminalExpression and TerminalExpression classes. invoke the Interpret operation.
  • Example
  1. “韶粵通”公交车读卡器可以判断乘客的身份,如果是“韶关”或者“广州”的“老人” “妇女”“儿童”就可以免费乘车,其他人员乘车一次扣 2 元。
  2. <expression> ::= <city>的<person> 、 <city> ::= 韶关|广州 、 <person> ::= 老人|妇女|儿童
//抽象表达式类
interface Expression {
    public boolean interpret(String info);
}

//终结符表达式类
class TerminalExpression implements Expression {
    private Set<String> set = new HashSet<String>();
    
    public TerminalExpression(String[] data) {
        for (int i = 0; i < data.length; i++) set.add(data[i]);
    }

    public boolean interpret(String info) {
        if (set.contains(info)) {
            return true;
        }
        return false;
    }
}

//非终结符表达式类
class AndExpression implements Expression {
    private Expression city = null;
    private Expression person = null;

    public AndExpression(Expression city, Expression person) {
        this.city = city;
        this.person = person;
    }

    public boolean interpret(String info) {
        String s[] = info.split("的");
        return city.interpret(s[0]) && person.interpret(s[1]);
    }
}

//环境类
class Context {
    private String[] citys = {"韶关", "广州"};
    private String[] persons = {"老人", "妇女", "儿童"};
    private Expression cityPerson;

    public Context() {
        Expression city = new TerminalExpression(citys);
        Expression person = new TerminalExpression(persons);
        cityPerson = new AndExpression(city, person);
    }

    public void freeRide(String info) {
        boolean ok = cityPerson.interpret(info);
        if (ok) System.out.println("您是" + info + ",您本次乘车免费!");
        else System.out.println(info + ",您不是免费人员,本次乘车扣费2元!");
    }
}

3.4 迭代器(Iterator)

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

  • Structure

在这里插入图片描述

  1. Iterator:defines an interface for accessing and traversing elements.
  2. ConcreteIterator:implements the Iterator interface. keeps track of the current position in the traversal of the aggregate.
  3. Aggregate:defines an interface for creating an Iterator object.
  4. ConcreteAggregate:implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

3.5 中介者(Mediator)

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping object from referring to each other explicitly, and it lets you vary their interaction independently.

在这里插入图片描述

The mediator serves as an intermediary that keeps objects in the group from referring to each other explicitly.

在这里插入图片描述

  1. Mediator:defines an interface for communicating with Colleague objects.
  2. ConcreteMediator:implements cooperative behavior by coordinating Colleague objects. knows and maitains its colleagues.
  3. Colleague classes:each Colleague class knows its Mediator object. each Colleague communicates with its mediator whenever it would have otherwise communicated with another colleague.

3.6 备忘录(Memento)

Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.

  • Structure

在这里插入图片描述

  1. Memento:stores internal state (not have to all) of the Originator object. protects against access by objects other than the originator. Ideally, only the originator that produced the memento would be permitted to access the memento’s internal state.
  2. Originator:creates a memento containing a snapshot of its current internal state. use the memento to restore its internal state.
  3. Caretaker:is responsible for the memento’s safekeeping. never operates on or examines the contents of the memento.

3.7 观察者(Observer)

(Pub-Sub)Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

  • Structure

在这里插入图片描述

  1. Subject:knows its observers. Any numbers of Observer objects may observe a subject. provides an interface for attaching and detaching Observer objects.
  2. Observer:defines an updating interface for objects that should be notified of changes in a subject.
  3. ConcreteSubject:stores state of interest to ConcreteObserver objects. sends a notification to its observers when its state changes.
  4. ConcreteObserver:maintains a reference to a ConcreteSubject object. stores state that should stay consistent with the subject’s. implements the Observer updating interface to keep its state consistent with the subject’s.

3.8 状态(State)

(Objects for states)Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

  • Structure

在这里插入图片描述

When a TCPConnection object receives requests from other objects, it responds differently depending on its current state.

在这里插入图片描述

  1. Context(TCPConnection):defines the interface of interest to clients. maintains an instance of a ConcreteState subclass that defines the current state.
  2. State(TCPState):defines an interface for encapsulating the behavior associated with a particular state of the Context.
  3. ConcreteState(TCPEstablished, TCPListen, TCPClosed):each subclass implements a behavior associated with a state of the Context.

3.9 策略(Strategy)

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

  • Structure
    在这里插入图片描述
  1. Strategy:declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.
  2. ConcreteStrategy:implements the algorithm using the Strategy interface.
  3. Context:is configured with a ConcreteStrategy object. maintains a reference to a Strategy object.

3.10 模板方法(Template Method)

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

  • Structure
    在这里插入图片描述
  1. AbstractClass:defines abstract primitive operations that concrete subclasses define to implement steps of an algorithm. implements a template method defining in the skeleton of an algorithm. The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects.
  2. ConcreteClass:implements the primitive operations to carry out subclass-specific steps of the algorithm.

3.11 访问者(Visitor)

(对数据的操作与数据结构分离)将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。

  • Structure
    在这里插入图片描述
  1. Visitor:declares a Visit operation for each class of ConcreteElement in the object structure. The operation;s name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the element directly through its particular interface.
  2. ConcreteVisitor:implements each operation declared by Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class of object in the structure. ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.
  3. Element:defines an Accept operation that takes a visitor as an argument.
  4. ConcreteElement:implements an Accept operation that takes a visitor as an argument.
  5. ObjectStructure:can enumerate its elements. may provide a high-level interface to allow the visitor to visit its elements. may either be a composite or a collection such as a list or a set.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值