面向对象设计模式

2023-11-13

一、创建型设计模式

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

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.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面向对象设计模式 的相关文章

随机推荐

  • 【图像分类】 可解释性神经网络(可视化):CAM/Grad-CAM pytorch相关代码

    目录 前言 类激活图 CAM class activation map 可视化 1 1 CAM的工作原理 2 基于梯度的CAM Grad CAM pytorch 实现 Grad CAM 前言 神经网络往往被称为 黑盒 Model学到的知识很
  • flink kafka 消费以及生产并行度设置

    相同点都是 前面并行度 后面并行度 也就是要求前面并行度 gt 后面并行度 1 flink consumer kafka数据 mod kafka partiton flink 并行度 1 1 kafka flink 并行度 一对一的关系 1
  • java版仿拼多多Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城 直播带货商城 电子商务 拼团商城源码

    1 涉及平台 平台管理 商家端 PC端 手机端 买家平台 H5 公众号 小程序 APP端 IOS Android 微服务平台 业务服务 2 核心架构 Spring Cloud Spring Boot Mybatis Redis 3 前端框架
  • 最近抖音很火的情侣飞行棋html源码

    演示网站如下 https effect guoyaxue top fxq index html 游戏规则 1 摇筛子自动走棋 2 每个格子都有任务 也可以自行商量执行其他任务 3 率先走到终点的一方 获得胜利 2023 抖音情侣飞行棋网站源
  • 爬虫之lxml模块和xpath

    lxml模块 lxml 库是一款 Python 数据解析库 参考重要文档在 lxml Processing XML and HTML with Python 项目开源地址在 GitHub lxml lxml The lxml XML too
  • 服务器硬盘销售渠道,存储服务器硬盘的选择及几个疑问解答

    在存储服务器硬件设备里最重要的肯定是硬盘了 因为所有的数据都保存在里面 虽然我们可以做阵列来提高安全性 但一般的RAID5 RAID6只能保证1到2块盘损坏的情况下数据是完整的 再损坏数据就要丢失了 所以选择性能好寿命长的硬盘才是解决问题的
  • Installshield 中 添加环境变量、设置右键菜单功能

    一 添加环境变量 首先设置feature new一个组件 环境变量将依附在这个组件上 如下图所示 a Component即刚刚设置feature时产生的 是该环境变量依赖的组件 Value值是想加入Path中的值 b OnInstall 如
  • 题目描述已知矩形的长和宽,计算其周长和面积。

    1010 矩形的周长和面积 1级 时间限制 1 Sec 内存限制 128 MB 提交 777 解决 442 提交 状态 讨论版 命题人 admin 题目描述 已知矩形的长和宽 计算其周长和面积 输入 仅一行 用空格隔开的两个整数 表示矩形的
  • 如何使用apt-cache搜索来查找软件包?

    这篇已经讲得很详细了 留言记录 如何使用apt cache搜索来查找软件包 腾讯云开发者社区 腾讯云
  • EJB分布式应用中需注意的问题

    1 EJB事务 EJB和spring事务都只能对RuntimeException进行事务回滚 所以要进行事务回滚的BO要throw RMSSysException而不是RMSAppException 现在的做法是在生成EJB代码时将RmsA
  • 2019.04.08—Java 中字母汉字占几个字节

    今天在做回顾的时候看到的问题 为什么两个运行的结果不一样呢 1 弄清java中的字节与字符 问题 在java中 一个字符等于多少字节 或者更详细的问 在java中 一个英文字符等于多少字节 一个中文字符等于多少字节 答案 Java采用uni
  • C++与Python混编——使用Pyhon扩展C++程序(1)

    在正式开始python与C 之间混合编程前 我们先从python官方文档中查看相关的资料 https docs python org 3 6 extending embedding html 本文及接下来相关博文 均已 vs2017 pyt
  • 命令行批量缩小图片尺寸

    最近要邮件发一批图片 可是图片文件总容量太大 每个都有2M多 需要缩小一下 就上网找了一下批量缩放图片大小的工具发现了Imagemgick这个好东西 Imagemgick是一个可以通过命令行对文件进行处理的程序 支持linux Mac OS
  • 常用shell命令

    查找字符串 grep r struct event base n 在当前目录查找字符串 找到后返回文件和对应的行 统计文件行数 字节 字数 wc命令 选项 l c w分别统计行数 字节 字数 可统计多文件 但不能统计目录 wc c main
  • 结构化程序设计:输入一个正整数(不超过5位数),输出由该数的各位能表示的最大数和最小数。

    结构化程序设计 输入一个正整数 不超过5位数 输出由该数的各位能表示的最大数和最小数 思路 代码 分析 1 分离x各位数到数组a中 2 对数组a进行排序 3 根据乘权求和算法 对已排好序的数组a分别从大到小和从小到大计算最大最小值 思路 首
  • ytht & infomall.cn

    为什么无法访问三角地版 近来有很多公众网用户无法访问三角地版 甚至一访问三角地版就会导致 IP 被自动封禁 从而无法继续连接一塌糊涂 为什么会出现这种奇怪的现象呢 我们的技术人员经过研究发现 只要您浏览包含有 triangle 字样的链接
  • 3D 贴图丢失的检测以及解决办法大全

    现在大部分设计师建好模型直接会丢在网上渲染 渲染完成后直接可以本地电脑下载结果 这样可以给行内设计师解决大部分渲图时间 但平时我们渲图会出现贴图丢失的情况 这到底是怎么回事 应该怎么解决这个问题呢 今天我做了个详细的归档 可以检测下贴图丢失
  • office全家桶_5个免费实用的Office学习网站,请马住

    我经常收到后台的私信或者现实生活周边的朋友咨询 有什么免费实用的Office学习教程或者网站 这倒是个大需求 基本只要涉及点到需要处理文字 数据等的工作都会要求会一点Office办公软件 当然了 岗位的不太所需要的Office熟练程度会有不
  • Linux :: 权限篇【2】:详解文件操作权限表示方式!字符表示法 及 八进制表示法说明!

    系列文章说明 前言 本篇是 Linux 基本操作篇章的内容 笔者使用的环境是基于腾讯云服务器 CentOS 7 6 64bit 学习集推荐 C 入门到入土 学习合集 Linux 从命令到网络再到内核 学习合集 文章目录 系列文章说明 前言
  • 面向对象设计模式

    文章目录 一 创建型设计模式 1 1 单例 Singleton 1 2 原型 Prototype 1 3 工厂 Factory 1 3 1 简单工厂 1 3 2 工厂方法 1 3 3 抽象工厂 1 4 建造者 Builder 二 结构型设计