Home >Java >javaTutorial >Common design patterns in java
Java Design Patterns;
A programmer’s understanding of Java Design Patterns:
“I don’t understand” why something very simple should be made so complicated. Later, as my experience in software development increased, I began to understand that the "complexity" I saw was exactly the essence of design patterns. What I understood as "simplicity" was the pattern of using a key to open a lock, and the purpose was just to focus on To solve the current problem, the "complexity" of the design pattern lies in that it is to construct a "master key" with the purpose of proposing a solution for unlocking all locks. Before I really understood design patterns, I had been writing "simple" code.
This "simple" is not the simplicity of function, but the simplicity of design. A simple design means a lack of flexibility. The code is very rigid and is only useful in this project. If it is used in other projects, it will be garbage. I call it "disposable code".
-->To make the code reusable, please use 'design patterns' to design your code.
Many programmers I know have a feeling of regret after being exposed to design patterns. Some people describe that after learning design patterns, they feel as if they have been reborn and reached a new level. Some even regard whether they understand design patterns as a criterion for classifying programmers' levels.
We can’t fall into the trap of patterns and apply patterns in order to use patterns, otherwise we will fall into formalism. When we use a pattern, we must pay attention to the intent of the pattern and not pay too much attention to the implementation details of the pattern, because these implementation details may change under specific circumstances. Don't stubbornly believe that the class diagram or implementation code in a design pattern book represents the pattern itself.
Design principles: (Important)
1.
Logic code is separated into separate methods, focusing on encapsulation - easy to read and reuse.
Don’t write hundreds of lines of logic code in one method. Separate each small logic code and write it in other methods, which is easy to read and can be called repeatedly.
2.
When writing classes, methods, and functions, you should consider portability and reusability: prevent one-time code!
Can I get it from other similar things? Is it possible to get it in other systems?
3.
Proficiently use the idea of inheritance:
Find out the similarities in the application and things that are not easy to change, extract them into abstract classes, and let subclasses inherit them;
The idea of inheritance also facilitates Your own logic is based on the results of others. Such as ImageField extends JTextField;
Proficient in using the idea of interfaces:
Find out the areas that may need to be changed in the application, separate them, and do not mix them with code that does not need to be changed.
Make a very simple thing so complicated, one-time code, an example of the advantages of design pattern: (Strategy mode)
Description:
A simulation duck game application, requirements: Various colors and shapes will appear in the game Ducks swim and play in the water while quacking.
The first method: (one-time code)
Directly write the classes of various ducks: MallardDuck//Wild duck, RedheadDuck//Red-headed duck. There are three methods for each type:
quack(): quacking method
swim( ): swimming method
display(): appearance method
Second method: Use inherited characteristics to improve the common parts and avoid repeated programming.
That is: design a duck superclass (Superclass) and let various ducks inherit this superclass.
public class Duck{
public void quack(){ quack’s, System.out.println(" swimming") ;
} b Public AbstratAct Void Display ();/*Because the appearance is different, let the subclass make it yourself. */
}
Just simply inherit its subclasses and implement your own display() method.
//MallardDuck
public class MallardDuck extends Duck{
public void display(){
}
}
//Red-headed duck
public class RedheadDuck extends Duck {L public void display () {
system.out.println ("color of red -headed duck ..."); . For us OO programmers, this couldn’t be simpler, just add one to the super class
Just one method is enough.
public class Duck{
public void quack(){ quack’s, System.out.println(" swimming") ;
}
public abstract void display(); /*Because the appearance is different, let the subclasses decide by themselves. */
public void fly(){
System.out.println("Fly! Duck");
}
}
For ducks that cannot fly, they only need to be simply overridden in subclasses.
// Disabled Duck
public class DisabledDuck extends Duck{
public void display(){
System.out.println("The color of the disabled duck...");
}
public void fly(){
//Override , and become doing nothing.
}
}
Other flying ducks do not need to be covered.
In this way, all ducks that inherit this super class will fly. But the problem came up again, and the customer pointed out that some ducks can fly and some cannot fly.
>>>> Yes, when one class changes, another class also changes, which is a bit inconsistent with OO design. This is obviously coupled together. Use inheritance-->The degree of coupling is too high.
The third method:
Use interface improvements.We extract the parts that are prone to change and encapsulate them to cope with future changes. Although the amount of code has increased, the usability has been improved and the degree of coupling has been reduced.
public interface Flyable{
public void fly();
}
public void quack();
}
The final design of Duck became:
public class Duck{
public void swim(){ //Swimming O System.out.println ("Swimming");
}
Public Abstract void void display (); /*Because the appearance is different, the subclass is decided. */
}
And MallardDuck, RedheadDuck, DisabledDuck can be written as:
//Wild Duck
public class MallardDuck extends Duck implements Flyable,Quackable{
public void display(){
System.out.println("The color of the wild duck. ..");
}
public void fly(){
//Implement this method
}
public void quack(){
//Implement this method
}
}
//Red-headed duck
public class RedheadDuck extends Duck implements Flyable,Quackable{
public void display(){
System.out.println("The color of the red-headed duck...");
}
public void fly(){
//Implement this method
}
public void quack(){
//Implement this method
}
}
//Disabled Duck only implements Quackable (can bark but not fly)
public class DisabledDuck extends Duck implements Quackable{
public void display(){
System.out.println ("The color of the crippled duck...");
}
public void quack(){
//Implement this method
}
}
>>>>>>Comments:
Benefits:
Designed in this way, our program reduces the coupling between them.
Disadvantages:
Flyable and Quackable interfaces seemed pretty good at first, solving the problem (Flyable can only be implemented by ducks that can fly), but Java interfaces do not have implementation code, so implementing interfaces cannot achieve code reuse.
Fourth method:
Summary of the above methods:
Benefits of inheritance: common parts can be reused and avoid duplication of programming.
We have a design principle:
Find out the similarities in the application and things that are not easy to change, Extract them into abstract classes and let subclasses inherit them;Find out the areas that may need to change in the application, separate them, and don't mix them with code that doesn't need to change. -->important.
Now, in order to separate the "changing and unchanged parts", we are going to create two sets of classes (completely away from the Duck class), one is related to "fly", and the other
is "quack" ” related, each set of classes will implement their own actions. For example, we may have one class that implements "croaking", another class that implements "squeaking", and another class that implements "quiet".
public interface FlyBehavior{
public void fly();}
public interface QuackBehavior{public void quack();
} We are defining some specific functions for FlyBehavior accomplish.
public class FlyWithWings implements FlyBehavior{
public void fly(){
//Implements the flight behavior of all ducks with wings.
}
}
public class FlyNoWay implements FlyBehavior{
public void fly(){
// Do nothing, can’t fly
}
}
public class Quack implements QuackBehavior{
Public void quack(){
//Implementing a quacking duck
}
}
public class Squeak implements QuackBehavior{
public void quack(){
//Implementing a squeaking duck
}
}
public class MuteQuack implements QuackBehavior{
public void quack(){
//Does nothing, won’t scream
}
}
Comment 1:
This design allows flying and quacking actions Reused by other objects, because these behaviors are no longer relevant to the duck class. And when we add some new behaviors, it will not affect the existing behavior classes, nor will it affect the duck classes that "use" flight behavior.
Finally let’s see how Duck is designed.
public class Duck{ ---------> In the abstract class, declare each interface and define the method corresponding to each interface.
throughmb out through out through out outmb out out together out together out out out out out out’’ out out out out out out out ’'s ‐ ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ public Duck( ){}
}
public void performQuack(){
}
}See how MallardDuck does it.
-----> Through the construction method, generate instances of the specific implementation classes of 'fly' and 'call', thereby specifying the specific properties of 'fly' and 'call'
public class MallardDuck extends Duck{
public MallardDuck { . flyBehavior = new FlyWithWings ();
quackBehavior = new Quack();
//Because MallardDuck inherits Duck, all have flyBehavior and quackBehavior instance variables }
public void display(){
// Implement
}
}
That’s it When you are satisfied, you can fly, bark, and show your colors at the same time.
We only need to add two methods to Duck.
public class Duck{
FlyBehavior flyBehavior;//Interface
QuackBehavior quackBehavior;//Interface
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior {
this.quackBehavior= quackBehavior;
}
}
---------------------- static Factory Method (static factory) ----- --------------------
(1)
In the design pattern, Factory Method is also a relatively simple one, but it is widely used, EJB, RMI, COM, CORBA , the shadow of this pattern
Basic concept:
FactoryMethod is a Creativity pattern, which defines an interface for creating objects, but lets subclasses decide which class to instantiate.
Usually we use Factory Method as a standard method of creating objects
When. When a class cannot predict what kind of object it will create or when a class needs a subclass to specify the object to be created, we need to use the Factory Method pattern.
Basic concept:
Singleton is a creative model, which is used to ensure that only one instance is generated and provides a global access point to access it. For some classes, it is guaranteed that only An instance is very important. For example, sometimes, database connections or Socket connections are subject to certain restrictions, and only one connection must exist at the same time.
Usage:
is to use static variables;
Example 1:
public class Singleton { private static Singleton s;
public static Singleton getInstance() {
if (s == null)
s = new Singleton();
Return s;
}
}
// Test class
class singletonTest {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
if (s1==s2)
System.out.println("s1 is the same instance with s2");
else
System.out.println("s1 is not the same instance with s2");
}
} The result of
singletonTest is:
s1 is the same instance with s2
(3)
Example 2:
class Singleton {
static boolean instance_flag = false; // true if 1 instance
public Singleton() {
if (instance_flag)
throw new SingletonException("Only one instance allowed");
else
instance_flag = true; // set flag for 1 instance
. - Observer Pattern (Observer) --------------------------------
(1)
Observer The pattern is a behavioral pattern, and its intention is to define a one-to-many dependency relationship between objects. When the state of an object changes, all objects that depend on it are notified and automatically updated.
The key objects of this pattern are Subject and Observer. A target can have any number of observers that depend on it. Once the target's state changes, all observers are notified. In response to this notification, each observer will query the target to make its state consistent with the target's. Status synchronization.
Thought:
(1)Establish the target (subject) and observer (observer) interface:
Target (subject) interface:
Establish an interface for registering observer objects; public void attach(Observer o) ;
Establish an interface for deleting observer objects; public void detach(Observer o);
Establish an interface for publishing notifications to observer objects when the target state changes; public void notice();
observer(observer )Interface:
Establish an update interface after receiving the target notification: public void update();
(3)
Example:
(Subject), and the students are the observers who need to know the information. When the teacher’s phone number changes, the students are notified and the corresponding phone records are updated
Subject code:
public interface Subject{ public void attach(Observer o);
public void detach(Observer o);
public void notice();
}
Observer code:
public interface Observer{
}
Teacher code;
import java.util.Vector;
private String phone;
private Vector students;
public Teacher(){
phone = "";
students = new Vector(); } L Public void notice () {
for (int i = 0; i & lt; studers.size (); I ++)
(observr). ONE (ONE String phone){
this.phone = phone;
notice(); using using using using using ‐ ’ ‐ ‐ ‐‐‐‐‐‐‐‐ } ‐ } ‐ } }
Student代码:
public class Student implements Observer{
private String name;
private String phone;
private Teacher teacher;
public Student(String name,Teacher t){
this.name = name;
teacher = t;
}
public void show(){
System.out.println("Name:"+name+"nTeacher'sphone:"+phone);
}
public void update(){
phone = teacher.getPhone();
}
}
Client代码:
package observer;
import java.util.Vector;
public class Client{ -->可以只定义目标者,观察者,另外的vector,只为了输入结果.
public static void main(String[] args){
Vector students = new Vector();
Teacher t = new Teacher();
for(int i= 0 ;i29ecb8685301674b955278013967bff6important.
*/
public Item first();
public Item next();
public boolean isDone();
public Item currentItem();
}
Controller类实现了Iterator接口。
package iterator;
import java.util.Vector;
public class Controller implements Iterator{
private int current =0;
Vector channel;
public Controller(Vector v){
channel = v;
}
public Item first(){
current = 0;
return (Item)channel.get(current);
}
public Item next(){
current ++;
return (Item)channel.get(current);
}
public Item currentItem(){
return (Item)channel.get(current);
}
public boolean isDone(){
return current>= channel.size()-1;
}
}
Television interface:
package iterator;
import java.util.Vector;
public interface Television {
Public Iterator createIterator();
}
The HaierTV class implements the Television interface.
package iterator;
import java.util.Vector;
public class HaierTV implements Television{ ---Object
private Vector channel;
public HaierTV(){
channel = new Vector();
channel.addElement(new Item( "channel 1")); --Each element is stored in VECTOR
channel.addElement(new Item("channel 2"));
channel.addElement(new Item("channel 3"));
channel.addElement(( new Item("channel 4"));
channel.addElement(new Item("channel 5"));
channel.addElement(new Item("channel 6"));
channel.addElement(new Item("channel 7"));
}
public Iterator createIterator(){
return new Controller(channel); --Put this VECTOR into the constructor of the iterator
}
}
Client:
package iterator;
public class Client{
public static void main(String[] args){
Television tv = new HaierTV();
Iterator it =tv.createIterator();
System.out.println(it.first().getName( ));
while(!it.isDone()){
System.out.println(it.next().getName());
}
}
}
Item class interface:
package iterator;
public class Item{
private String name;
public Item(String aName){
name = aName; -------------------- Facade -------------------- ------
(1)
Facade mode is a structural mode. Facade mode defines a high-level interface, which makes this subsystem easier to use.
The main purpose of the appearance mode is to provide convenient calling methods for the complex processing of subsystems, making the subsystem easier to use.
-->Include the complex process and provide a simple application interface.
For example, in the process of making tea, you need to do the following work: boil water, prepare tea, and Put the tea leaves in the quilt and put the boiling water in the tea cup. Only after these processes can you brew good tea leaves. This is a commonly used step. 80% of the tea making steps look like this. These actions can be linked together to form a whole step. The following example of MakeACuppa() uses the facade mode, so that in It is more convenient when calling step methods. This is the appearance mode, and the details inside are blocked.
public class TeaCup{.....}
public class TeaBag{.....}
public class Water{.....}
private boolean TeaBagIsSteeped;
public FacadeCuppaMaker () () {System.out.println ("Facadecuppamaker is ready to rush tea"); ew team ();
water water = new Water();cup.addFacadeTeaBag(teaBag);
water.boilFacadeWater();cup.addFacadeWater(water);
cup.steepTeaBag();
---- -------------------------- Adapter mode (adapter) ------------------ ------------
(1)The purpose of the adapter pattern is to reuse an existing class/interface and convert/concrete it into another class/interface that the customer wants.
(2)
How to reuse instances:
Put the class to be reused into the construction method of the target class, instantiate it, and then call it in the corresponding method of the target class to modify the original method
Parameters in
, or add corresponding logic. That is, the original methods of existing classes are reused.
Class to be reused:
public class Adaptee{
public long getPower(long base,long exp){
long result=1;
for(int i=0;i180d310446dc54a396a13811f9fcab40 While indirectly accessing the object, you can add other logic code before or after it.
--->Yes The original logic adds other logic and finally generates new logic. That is: adding some additional logic to the class method and generating new method logic.
(2)
Static proxy:
--> Both implement a common interface or inherit the same abstract class;
--> Just instantiate the original class in the proxy class and add new logic before and after the original class method.象 Below: 角 Abstract characters:
abstract Public Class Subject
{
Abstract Public Void Request (); Public void request () {
system.out. println("From real subject.");
}
}
Proxy role:
public class ProxySubject extends Subject
{
private RealSubject realSubject; //Use the real role as the attribute of the proxy role
public ProxySubject()
{ realSubject=new RealSubject(); }
public void request() // Same as the original method name { postRequest();
private void preRequest()
Client call:
Sub.request();
Dynamic proxy class
The Java dynamic proxy class is located under the Java.lang.reflect package and generally involves the following two Classes:
Interface InvocationHandler: Only one method is defined in this interface: invoke(Object obj, Method method, Object[] args)
. In actual use, the first parameter obj generally refers to the proxy class, method is the proxy method, and args is the parameter array of the method. This abstract method
is implemented dynamically in the proxy class.
2)Proxy: This class is a dynamic proxy class, which mainly includes the following content:
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h): Returns the proxy class
, the returned proxy class can be used as the proxy class.
The so-called Dynamic Proxy is a class: it is a class generated at runtime. When generating it, you must provide a set of interfaces to it, and then
the class declares that it implements these interfaces.
3)
When using a dynamic proxy class, we must implement the InvocationHandler interface,
public interface Subject
{
Public void request();
}
Specific role RealSubject: Same as above;
Agent role:
import java.lang .reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject(Object obj) {
sub = obj;
}
public Object invoke(Object proxy , Method method, Object[] args) throws Throwable {
System.out.println("before calling " + method);
method.invoke(sub,args);
System.out.println("after calling " + method);
Return null;
}
}
==>
method.invoke(sub,args);
In fact, it is to call the method to be executed of the proxy object, and the method parameter sub is the actual proxy Object, args are the parameters required to perform the corresponding operation of the proxy object. Through dynamic proxy classes, we can perform some related operations before or after the call.
Client:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Client
static public void main(String[] args) throws Throwable
{
RealSubject rs = new RealSubject(); //Specify the proxy class here
InvocationHandler ds = new DynamicSubject(rs); //Initialize the proxy class
Subject subject = (Subject) Proxy.newProxyInstance(rs.getClass().getClassLoader(),rs.getClass
().getInterfaces(),ds );
}
5)
package dynamicProxy;
public interface Work {
public void startWork();
}
package dynamicProxy;
public void startWork() {
System.out.println("jason start to work...");
}
}
public interface Play {
}
public class JasonPlay implements Play {
System.out.println("jason start to play...");
}
}
public class Test {
{
;
Work jasonproxy=(Work)Proxy.newProxyInstance(work.getClass().getClassLoader(),
work.getClass().getInterfaces(), dynamicProxy); JasonPlay play=new JasonPlay();
InvocationHandler dynamicProxy=new DynamicProxy(play);
play.getClass().getInterfaces(), dynamicProxy);
}
}
===>Dynamic proxy class can be combined with any type of real class (work/play) to perform dynamic proxying.
------------------------------- State mode (state) --------------- ----------------
(1)State mode definition:
Different states, different behaviors; In other words, each state has a corresponding behavior.Applicable occasions:
State mode is more common in actual use and is suitable for "state switching". Because we often use If elseif else to switch states. If such judgment switching of the state occurs repeatedly, we have to think about whether the State mode can be adopted.
-->Suitable for internal states that constantly change in cycles.
(2)
A state consists of two parts: object + properties inside the object (property interface + specific properties)
An object must have its properties , as well as its setter and getter. And set its initial state + a method to call the display state (in which the state calls its own display method).
A specific property must contain When the object is entered, in the implementation method, the next attribute to be displayed of the object must be set --> so that the next time the object calls the method, its attribute value will change.
The difference between state mode and observer mode:
State mode, like observer mode, is a one-to-many mode. But in the observer mode, if "one" changes, all "many" will also be updated.
The state mode emphasizes that "many" are the states of "one", and the states of "one" are in a continuous cycle.
How to establish a relationship between one and many:
"Many" all implement an interface. Therefore, in the class of "one", the interface of "many" is declared; if you want to establish a relationship with "one" in "many", you only need to declare "one" directly in the class.
(3)
Code:
public interface Color {
public void show();
}
package state;
class Light
{
Color color;
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public Light()
{
color=new RedColor(this);
}
public void showColor()
{
color.show();
}
}
class RedColor implements Color
{
Light light;
public RedColor(Light light)
{
this.light=light;
}
public void show()
{
System.out.println("the color is red, the car must stop!");
System.out.println("write down all logic shoud do this in this state.....");
light.setColor(new GreenColor(light));
}
}
class GreenColor implements Color
{
Light light;
public GreenColor(Light light)
{
this.light=light;
}
public void show ()
{
System.out.println("the color is green, the car can run !");
System.out.println("write down all logic shoud do this in this state....") ;
light.setColor(new YellowColor(light));
}
}
class YellowColor implements Color
{
Light light;
public YellowColor(Light light)
{
this.light=light;
}
public void show()
{
System.out.println("the color is yellow, the car shoud stop !");
System.out.println("write down all logic shoud do this in this state..... ");
light.setColor(new RedColor(light));
}
}
public class CarLight {
public static void main(String[] args) {
Light light=new Light();
// The initial call is red light
light.showColor();
//Then it is called green light
light.showColor();
//Then it is called yellow light
light.showColor();
//Continuously calling and looping.
}
}
------------------------------ Flyweight mode (Flyweight) -- -----------------------------
(1)
It is mainly used to use sharing technology when creating objects to reduce the memory usage of objects. Occupy. A mode that improves the efficiency and performance of the program will greatly speed up the operation of the program. That is to say, if there are multiple identical objects in a system, then only one copy can be shared. It is not necessary for each To instantiate an object.
Factory mode often appears in Flyweight mode. Flyweight's internal state is for sharing, and Flyweight factory is responsible for maintaining an object storage pool (Flyweight Pool) to store internal state objects.
When creating a new object:
First get it from the hashtable --> Determine whether the obtained object is empty --> If so, create a new object and put it back into the hashtable --> If it exists, share the original object.
(2)
Instance: (Compare with static factory mode)
public void showCarName();
}
class BMWCar implements Car
{
{
System.out.println("this is the BMWCar ."); }
}
class FordCar implements Car
{
public void showCarName()
{
}
}
class CarFactory
{
public static Car car;
public static Car getCar(String name)
if("BMW".equals(name))
{
car = new BMWCar();
}
if("Ford".equals(name))
{
car = new FordCar();
}
return car;
}
}
class CarFlyWeightFactory
{
public Car car;
private Hashtable219f70c21f651df0c8fbe73f27fa1bf8 carPool=new Hashtable219f70c21f651df0c8fbe73f27fa1bf8();
public Car getCar(String name)
{
if("BMW".equals(name))
{
car=carPool.get(name);
if(car==null)
{
car=new BMWCar();
carPool.put(name, car);
}
}
if("Ford".equals(name))
{
car=carPool.get(name);
if(car==null)
{
car=new FordCar();
carPool.put(name, car);
}
}
return car;
}
public int getNumber(){ return carPool.getSize(); }
}
public class Test {
public static void main(String[] args) {
CarFlyWeightFactory carFlyWeightFactory=new CarFlyWeightFactory();
Car carf1=carFlyWeightFactory.getCar("Ford");
carf1.showCarName();
Car carf2=carFlyWeightFactory.getCar("Ford");
carf2.showCarName();
if(carf1==carf2)
{
System.out.println("同一部车来的");
}
else
{
System.out.println("不同一部车来的");
}
System.out.println("车的数量是:"+carFlyWeightFactory.getNumber());
}
}
输出:
this is the FordCar .
this is the FordCar .
同一部车来的
---------------------- 职责链模式(Chain of Responsibility) -----------------------
(1)
Chain of Responsibility职责链模式:
为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
-->
要沿着链转发请求,并保证接受者为隐式的,每个链上的对象都有一致的处理请求和访问链上后继者的接口(即如下实例中,在自己方法中再调用一次相同的方法)。
(2)
public class Boy {
private boolean hasCar; // 是否有车
private boolean hasHouse; // 是否有房
private boolean hasResponsibility; // 是否有责任心
public Boy() {
}
public Boy(boolean hasCar, boolean hasHouse, boolean hasResponsibility) {
this.hasCar = hasCar;
this.hasHouse = hasHouse;
this.hasResponsibility = hasResponsibility;
}
public boolean isHasCar() {
return hasCar;
}
public void setHasCar(boolean hasCar) {
this.hasCar = hasCar;
}
public boolean isHasHouse() {
return hasHouse;
}
public void setHasHouse(boolean hasHouse) {
this.hasHouse = hasHouse;
}
public boolean isHasResponsibility() {
return hasResponsibility;
}
public void setHasResponsibility(boolean hasResponsibility) {
this.hasResponsibility = hasResponsibility;
}
}
public interface Handler {
public void handleRequest(Boy boy);
}
public class HouseHandler implements Handler {
private Handler handler;
public HouseHandler(Handler handler) {
this.handler = handler;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handleRequest(Boy boy) {
if (boy.isHasHouse()) {
System.out.println("没想到吧,我还有房子");
} else {
System.out.println("我也没有房");
handler.handleRequest(boy);
}
}
}
public class CarHandler implements Handler {
private Handler handler;
public CarHandler(Handler handler) {
this.handler = handler;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handleRequest(Boy boy) {
if (boy.isHasCar()) {
System.out.println("Haha, I have a car");
} else {
System.out.println("I don’t have one) car");
handler.handleRequest(boy);
}
}
}
public class ResponsibilityHandler implements Handler {
private Handler handler;
public ResponsibilityHandler(Handler handler) {
this.handler = handler;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handleRequest(Boy boy) {
if (boy.isHasResponsibility( )) {
System.out.println("I only have a heart with Responsibility");
} else {
System.out.println("No sense of responsibility");
handler.handleRequest(boy);
}
}
}
public class Girl {
public static void main(String[] args) {
// This boy doesn’t have a car or a house, but he is very responsible
Boy boy = new Boy(false, false, true);
// You can also use the setHanlder method
Handler handler = new CarHandler(new HouseHandler(
new ResponsibilityHandler(null)));
How to make the request pass along the chain among the accepting objects. When it is not accepted by the first accepting object, it will be passed to the second object. If it is accepted by the first object, it will not be passed on:
1 .Each specific receiving object adopts the following construction method:
public CarHandler(Handler handler) { this.handler = handler; }
3. In the final test class, when generating a specific handler, use multi-layer inclusion Form. In this way, after calling the method of the previous layer car, the corresponding method of the house will be called, and finally the method of the ResponsibilityHandler is called.
==> The first two handlers use the construction method with parameters, and the last one It uses the NULL construction method
--------------------------------- Memento ---- -----------------------------
Memo mode is a behavioral mode, and its intention is to achieve encapsulation without destroying it. , captures the internal state of an object and saves this state outside the object, so that the object can be restored to its original saved state later.
(2)
The example is as follows:
There is an object Employee. In addition to attributes, a method to save and restore the state is also needed.
There is an object Memento, used to record the status of Employee at every moment,
package memento; public class Memento{ String name; int age; public Memento(String name,int age){ this.name = name; this.age = age; } }Employee mode:
package memento; public class Employee{ private String name; private int age; public Employee(String aName,int aAge){ name = aName; age = aAge; } public void setName(String aName){ name = aName; } public void setAge(int aAge){ age = aAge; } public Memento saveMemento(){ return new Memento(name,age); } public void restoreMemento(Memento memento){ age = memento.age; name = memento.name; } public int getAge(){ return age; } public String getName(){ return name; } }
package memento; import java.util.Vector; public class CareTaker{ private Vector v; private int current; public CareTaker(){ current = -1; v = new Vector(); } public void setMemento(Memento mem){ current ++; v.add(mem); } public Memento getMemento(){ if(current>0){ current --; return(Memento) v.get(current); } return null; } }Client code:
package memento; public class Client{ public static void show(Employee e){ System.out.println("-----------------------------------"); System.out.println("Name:"+e.getName()); System.out.println("Age:" + e.getAge()); System.out.println("-----------------------------------"); } public static void main(String[] args){ Employee e = new Employee("lili",25); CareTaker ct = new CareTaker(); show(e); ct.setMemento(e.saveMemento()); e.setName("litianli"); show(e); ct.setMemento(e.saveMemento()); e.setAge(45); show(e); ct.setMemento(e.saveMemento()); //restore e.restoreMemento(ct.getMemento()); show(e); e.restoreMemento(ct.getMemento()); show(e); } }